improve perf of instance select dropdown
This commit is contained in:
parent
74511c67dd
commit
0f2aa3c938
|
@ -1,10 +0,0 @@
|
||||||
import * as React from 'react';
|
|
||||||
import * as ReactDOM from 'react-dom';
|
|
||||||
|
|
||||||
import { App } from './App';
|
|
||||||
|
|
||||||
it('renders without crashing', () => {
|
|
||||||
const div = document.createElement('div');
|
|
||||||
ReactDOM.render(<App />, div);
|
|
||||||
ReactDOM.unmountComponentAtNode(div);
|
|
||||||
});
|
|
|
@ -10,7 +10,7 @@ import { fetchInstances } from './redux/actions';
|
||||||
import { IAppState, IInstance } from './redux/types';
|
import { IAppState, IInstance } from './redux/types';
|
||||||
|
|
||||||
interface IAppProps {
|
interface IAppProps {
|
||||||
currentInstance: IInstance | null;
|
currentInstanceName?: string | null;
|
||||||
instances?: IInstance[],
|
instances?: IInstance[],
|
||||||
isLoadingInstances: boolean,
|
isLoadingInstances: boolean,
|
||||||
fetchInstances: () => void;
|
fetchInstances: () => void;
|
||||||
|
@ -61,7 +61,7 @@ class AppImpl extends React.Component<IAppProps> {
|
||||||
className="fediverse-welcome"
|
className="fediverse-welcome"
|
||||||
icon={IconNames.SEARCH_AROUND}
|
icon={IconNames.SEARCH_AROUND}
|
||||||
title="Graph. TODO"
|
title="Graph. TODO"
|
||||||
description={"Selected " + ((this.props.currentInstance && this.props.currentInstance.name) || "nothing")}
|
description={"Selected " + (this.props.currentInstanceName || "nothing")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -70,7 +70,7 @@ class AppImpl extends React.Component<IAppProps> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state: IAppState) => ({
|
const mapStateToProps = (state: IAppState) => ({
|
||||||
currentInstance: state.currentInstance,
|
currentInstanceName: state.currentInstanceName,
|
||||||
instances: state.data.instances,
|
instances: state.data.instances,
|
||||||
isLoadingInstances: state.data.isLoadingInstances,
|
isLoadingInstances: state.data.isLoadingInstances,
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
// import { List, ListRowProps } from 'react-virtualized';
|
|
||||||
import { Dispatch } from 'redux';
|
import { Dispatch } from 'redux';
|
||||||
|
|
||||||
import { Button, MenuItem } from '@blueprintjs/core';
|
import { Button, MenuItem } from '@blueprintjs/core';
|
||||||
import { IconNames } from '@blueprintjs/icons';
|
import { IconNames } from '@blueprintjs/icons';
|
||||||
import { ItemPredicate, ItemRenderer, Select } from '@blueprintjs/select';
|
import { IItemRendererProps, ItemPredicate, Select } from '@blueprintjs/select';
|
||||||
|
|
||||||
import { selectInstance } from '../redux/actions';
|
import { selectInstance } from '../redux/actions';
|
||||||
import { IAppState, IInstance } from '../redux/types';
|
import { IAppState, IInstance } from '../redux/types';
|
||||||
|
|
||||||
interface IInstanceSearchProps {
|
interface IInstanceSearchProps {
|
||||||
currentInstance: IInstance | null;
|
currentInstanceName: string | null;
|
||||||
instances?: IInstance[];
|
instances?: IInstance[];
|
||||||
selectInstance: (instanceName: string) => void;
|
selectInstance: (instanceName: string) => void;
|
||||||
}
|
}
|
||||||
|
@ -28,33 +27,48 @@ class InstanceSearchImpl extends React.Component<IInstanceSearchProps> {
|
||||||
onItemSelect={this.onItemSelect}
|
onItemSelect={this.onItemSelect}
|
||||||
itemPredicate={this.itemPredicate}
|
itemPredicate={this.itemPredicate}
|
||||||
disabled={!this.props.instances}
|
disabled={!this.props.instances}
|
||||||
|
initialContent={this.renderInitialContent()}
|
||||||
|
noResults={this.renderNoResults()}
|
||||||
|
popoverProps={{popoverClassName: "fediverse-instance-search-popover"}}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
icon={IconNames.SELECTION}
|
icon={IconNames.SELECTION}
|
||||||
rightIcon={IconNames.CARET_DOWN}
|
rightIcon={IconNames.CARET_DOWN}
|
||||||
text={(this.props.currentInstance && this.props.currentInstance.name) || ("Select an instance")}
|
text={this.props.currentInstanceName || ("Select an instance")}
|
||||||
disabled={!this.props.instances}
|
disabled={!this.props.instances}
|
||||||
/>
|
/>
|
||||||
</InstanceSelect>
|
</InstanceSelect>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private itemRenderer: ItemRenderer<IInstance> = (item, { handleClick, modifiers }) => {
|
private renderInitialContent = () => {
|
||||||
if (!modifiers.matchesPredicate) {
|
return (
|
||||||
|
<MenuItem disabled={true} text={"Start typing"} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private renderNoResults = () => {
|
||||||
|
return (
|
||||||
|
<MenuItem disabled={true} text={"Keep typing"} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private itemRenderer = (item: IInstance, itemProps: IItemRendererProps) => {
|
||||||
|
if (!itemProps.modifiers.matchesPredicate) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
text={item.name}
|
text={item.name}
|
||||||
key={item.name}
|
key={item.name}
|
||||||
active={modifiers.active}
|
active={itemProps.modifiers.active}
|
||||||
onClick={handleClick}
|
onClick={itemProps.handleClick}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private itemPredicate: ItemPredicate<IInstance> = (query, item, index) => {
|
private itemPredicate: ItemPredicate<IInstance> = (query, item, index) => {
|
||||||
if (!item.name) {
|
if (!item.name || query.length < 4) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return item.name.toLowerCase().indexOf(query.toLowerCase()) >= 0;
|
return item.name.toLowerCase().indexOf(query.toLowerCase()) >= 0;
|
||||||
|
@ -66,7 +80,7 @@ class InstanceSearchImpl extends React.Component<IInstanceSearchProps> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state: IAppState) => ({
|
const mapStateToProps = (state: IAppState) => ({
|
||||||
currentInstance: state.currentInstance,
|
currentInstanceName: state.currentInstanceName,
|
||||||
instances: state.data.instances,
|
instances: state.data.instances,
|
||||||
})
|
})
|
||||||
const mapDispatchToProps = (dispatch: Dispatch) => ({
|
const mapDispatchToProps = (dispatch: Dispatch) => ({
|
||||||
|
|
|
@ -12,7 +12,7 @@ html, body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.fediverse-instance-search-popover {
|
.fediverse-instance-search-popover {
|
||||||
height: 350px;
|
max-height: 350px;
|
||||||
min-width: 214px;
|
min-width: 300px;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,9 @@ import { Dispatch } from 'redux';
|
||||||
import { getFromApi } from '../util';
|
import { getFromApi } from '../util';
|
||||||
import { ActionType, IInstance } from './types';
|
import { ActionType, IInstance } from './types';
|
||||||
|
|
||||||
export const selectInstance = (instance: string) => {
|
export const selectInstance = (instanceName: string) => {
|
||||||
return {
|
return {
|
||||||
payload: {
|
payload: instanceName,
|
||||||
instance,
|
|
||||||
},
|
|
||||||
type: ActionType.SELECT_INSTANCE,
|
type: ActionType.SELECT_INSTANCE,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { combineReducers } from 'redux';
|
import { combineReducers } from 'redux';
|
||||||
|
|
||||||
import { ActionType, IAction, IDataState, IInstance } from './types';
|
import { ActionType, IAction, IDataState } from './types';
|
||||||
|
|
||||||
const initialDataState = {
|
const initialDataState = {
|
||||||
isLoadingInstances: false,
|
isLoadingInstances: false,
|
||||||
|
@ -24,7 +24,7 @@ const data = (state: IDataState = initialDataState, action: IAction) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentInstance = (state: IInstance | null = null, action: IAction): IInstance | null => {
|
const currentInstanceName = (state: string | null = null, action: IAction): string | null => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case ActionType.SELECT_INSTANCE:
|
case ActionType.SELECT_INSTANCE:
|
||||||
return action.payload;
|
return action.payload;
|
||||||
|
@ -34,6 +34,6 @@ const currentInstance = (state: IInstance | null = null, action: IAction): IInst
|
||||||
}
|
}
|
||||||
|
|
||||||
export const rootReducer = combineReducers({
|
export const rootReducer = combineReducers({
|
||||||
currentInstance,
|
currentInstanceName,
|
||||||
data,
|
data,
|
||||||
})
|
})
|
|
@ -20,6 +20,6 @@ export interface IDataState {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IAppState {
|
export interface IAppState {
|
||||||
currentInstance: IInstance | null,
|
currentInstanceName: string | null,
|
||||||
data: IDataState,
|
data: IDataState,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import fetch from 'cross-fetch';
|
import fetch from 'cross-fetch';
|
||||||
|
|
||||||
// const API_ROOT = "https://fediverse.space/api/v1/"
|
const API_ROOT = "https://fediverse.space/api/v1/"
|
||||||
const API_ROOT = "http://localhost:8000/api/v1/"
|
// const API_ROOT = "http://localhost:8000/api/v1/"
|
||||||
|
|
||||||
export const getFromApi = (path: string): Promise<any> => {
|
export const getFromApi = (path: string): Promise<any> => {
|
||||||
const domain = API_ROOT.endsWith("/") ? API_ROOT : API_ROOT + "/";
|
const domain = API_ROOT.endsWith("/") ? API_ROOT : API_ROOT + "/";
|
||||||
|
|
Loading…
Reference in a new issue