tidy up the ref to ref with a forwardRef and initialComponent signature

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
pull/21833/head
Michael Telatynski 2020-05-30 13:30:59 +01:00
parent 8087b521e6
commit bc83984a62
7 changed files with 51 additions and 73 deletions

View File

@ -90,11 +90,12 @@ export default class CommunityProvider extends AutocompleteProvider {
type: "community", type: "community",
href: makeGroupPermalink(groupId), href: makeGroupPermalink(groupId),
component: ( component: (
<PillCompletion initialComponent={ <PillCompletion title={name} description={groupId}>
<BaseAvatar name={name || groupId} <BaseAvatar name={name || groupId}
width={24} height={24} width={24}
height={24}
url={avatarUrl ? cli.mxcUrlToHttp(avatarUrl, 24, 24) : null} /> url={avatarUrl ? cli.mxcUrlToHttp(avatarUrl, 24, 24) : null} />
} title={name} description={groupId} /> </PillCompletion>
), ),
range, range,
})) }))

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import React, {createRef} from 'react'; import React, {forwardRef} from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
/* These were earlier stateless functional components but had to be converted /* These were earlier stateless functional components but had to be converted
@ -30,62 +30,37 @@ interface ITextualCompletionProps {
className?: string; className?: string;
} }
export abstract class Completion<T> extends React.PureComponent<T> { export const TextualCompletion = forwardRef<ITextualCompletionProps, any>((props, ref) => {
nodeRef = createRef<HTMLDivElement>(); const {title, subtitle, description, className, ...restProps} = props;
return (
<div {...restProps}
className={classNames('mx_Autocomplete_Completion_block', className)}
role="option"
ref={ref}
>
<span className="mx_Autocomplete_Completion_title">{ title }</span>
<span className="mx_Autocomplete_Completion_subtitle">{ subtitle }</span>
<span className="mx_Autocomplete_Completion_description">{ description }</span>
</div>
);
});
interface IPillCompletionProps extends ITextualCompletionProps {
children?: React.ReactNode,
} }
export class TextualCompletion extends Completion<ITextualCompletionProps> { export const PillCompletion = forwardRef<IPillCompletionProps, any>((props, ref) => {
render() { const {title, subtitle, description, className, children, ...restProps} = props;
const { return (
title, <div {...restProps}
subtitle, className={classNames('mx_Autocomplete_Completion_pill', className)}
description, role="option"
className, ref={ref}
...restProps >
} = this.props; { children }
return ( <span className="mx_Autocomplete_Completion_title">{ title }</span>
<div {...restProps} <span className="mx_Autocomplete_Completion_subtitle">{ subtitle }</span>
className={classNames('mx_Autocomplete_Completion_block', className)} <span className="mx_Autocomplete_Completion_description">{ description }</span>
role="option" </div>
ref={this.nodeRef} );
> });
<span className="mx_Autocomplete_Completion_title">{ title }</span>
<span className="mx_Autocomplete_Completion_subtitle">{ subtitle }</span>
<span className="mx_Autocomplete_Completion_description">{ description }</span>
</div>
);
}
}
interface IPillCompletionProps {
title?: string;
subtitle?: string;
description?: string;
initialComponent?: React.ReactNode,
className?: string;
}
export class PillCompletion extends Completion<IPillCompletionProps> {
render() {
const {
title,
subtitle,
description,
initialComponent,
className,
...restProps
} = this.props;
return (
<div {...restProps}
className={classNames('mx_Autocomplete_Completion_pill', className)}
role="option"
ref={this.nodeRef}
>
{ initialComponent }
<span className="mx_Autocomplete_Completion_title">{ title }</span>
<span className="mx_Autocomplete_Completion_subtitle">{ subtitle }</span>
<span className="mx_Autocomplete_Completion_description">{ description }</span>
</div>
);
}
}

View File

@ -121,9 +121,9 @@ export default class EmojiProvider extends AutocompleteProvider {
return { return {
completion: unicode, completion: unicode,
component: ( component: (
<PillCompletion title={shortname} aria-label={unicode} initialComponent={ <PillCompletion title={shortname} aria-label={unicode}>
<span style={{maxWidth: '1em'}}>{ unicode }</span> <span style={{maxWidth: '1em'}}>{ unicode }</span>
} /> </PillCompletion>
), ),
range, range,
}; };

View File

@ -48,7 +48,9 @@ export default class NotifProvider extends AutocompleteProvider {
type: "at-room", type: "at-room",
suffix: ' ', suffix: ' ',
component: ( component: (
<PillCompletion initialComponent={<RoomAvatar width={24} height={24} room={this.room} />} title="@room" description={_t("Notify the whole room")} /> <PillCompletion title="@room" description={_t("Notify the whole room")}>
<RoomAvatar width={24} height={24} room={this.room} />
</PillCompletion>
), ),
range, range,
}]; }];

View File

@ -103,7 +103,9 @@ export default class RoomProvider extends AutocompleteProvider {
suffix: ' ', suffix: ' ',
href: makeRoomPermalink(room.displayedAlias), href: makeRoomPermalink(room.displayedAlias),
component: ( component: (
<PillCompletion initialComponent={<RoomAvatar width={24} height={24} room={room.room} />} title={room.room.name} description={room.displayedAlias} /> <PillCompletion title={room.room.name} description={room.displayedAlias}>
<RoomAvatar width={24} height={24} room={room.room} />
</PillCompletion>
), ),
range, range,
}; };

View File

@ -125,10 +125,9 @@ export default class UserProvider extends AutocompleteProvider {
suffix: (selection.beginning && range.start === 0) ? ': ' : ' ', suffix: (selection.beginning && range.start === 0) ? ': ' : ' ',
href: makeUserPermalink(user.userId), href: makeUserPermalink(user.userId),
component: ( component: (
<PillCompletion <PillCompletion title={displayName} description={user.userId}>
initialComponent={<MemberAvatar member={user} width={24} height={24} />} <MemberAvatar member={user} width={24} height={24} />
title={displayName} </PillCompletion>
description={user.userId} />
), ),
range, range,
}; };

View File

@ -23,7 +23,6 @@ import {Room} from 'matrix-js-sdk/src/models/room';
import SettingsStore from "../../../settings/SettingsStore"; import SettingsStore from "../../../settings/SettingsStore";
import Autocompleter from '../../../autocomplete/Autocompleter'; import Autocompleter from '../../../autocomplete/Autocompleter';
import { Completion } from '../../../autocomplete/Components';
const COMPOSER_SELECTED = 0; const COMPOSER_SELECTED = 0;
@ -254,10 +253,10 @@ export default class Autocomplete extends React.PureComponent<IProps, IState> {
componentDidUpdate(prevProps: IProps) { componentDidUpdate(prevProps: IProps) {
this.applyNewProps(prevProps.query, prevProps.room); this.applyNewProps(prevProps.query, prevProps.room);
// this is the selected completion, so scroll it into view if needed // this is the selected completion, so scroll it into view if needed
const selectedCompletion = this.refs[`completion${this.state.selectionOffset}`] as Completion<any>; const selectedCompletion = this.refs[`completion${this.state.selectionOffset}`] as HTMLElement;
if (selectedCompletion && selectedCompletion.nodeRef.current) { if (selectedCompletion) {
selectedCompletion.nodeRef.current.scrollIntoView({ selectedCompletion.scrollIntoView({
behavior: "auto", behavior: "auto",
block: "nearest", block: "nearest",
}); });