mirror of https://github.com/vector-im/riot-web
Merge pull request #6228 from matrix-org/gsouquet/fix-17673
commit
35b8f79fbd
|
@ -39,6 +39,9 @@ import ProgressBar from "../elements/ProgressBar";
|
||||||
import {SpaceFeedbackPrompt} from "../../structures/SpaceRoomView";
|
import {SpaceFeedbackPrompt} from "../../structures/SpaceRoomView";
|
||||||
import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar";
|
import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar";
|
||||||
import QueryMatcher from "../../../autocomplete/QueryMatcher";
|
import QueryMatcher from "../../../autocomplete/QueryMatcher";
|
||||||
|
import TruncatedList from "../elements/TruncatedList";
|
||||||
|
import EntityTile from "../rooms/EntityTile";
|
||||||
|
import BaseAvatar from "../avatars/BaseAvatar";
|
||||||
|
|
||||||
interface IProps extends IDialogProps {
|
interface IProps extends IDialogProps {
|
||||||
matrixClient: MatrixClient;
|
matrixClient: MatrixClient;
|
||||||
|
@ -204,6 +207,17 @@ export const AddExistingToSpace: React.FC<IAddExistingToSpaceProps> = ({
|
||||||
setSelectedToAdd(new Set(selectedToAdd));
|
setSelectedToAdd(new Set(selectedToAdd));
|
||||||
} : null;
|
} : null;
|
||||||
|
|
||||||
|
const [truncateAt, setTruncateAt] = useState(20);
|
||||||
|
function overflowTile(overflowCount, totalCount) {
|
||||||
|
const text = _t("and %(count)s others...", { count: overflowCount });
|
||||||
|
return (
|
||||||
|
<EntityTile className="mx_EntityTile_ellipsis" avatarJsx={
|
||||||
|
<BaseAvatar url={require("../../../../res/img/ellipsis.svg")} name="..." width={36} height={36} />
|
||||||
|
} name={text} presenceState="online" suppressOnHover={true}
|
||||||
|
onClick={() => setTruncateAt(totalCount)} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return <div className="mx_AddExistingToSpace">
|
return <div className="mx_AddExistingToSpace">
|
||||||
<SearchBox
|
<SearchBox
|
||||||
className="mx_textinput_icon mx_textinput_search"
|
className="mx_textinput_icon mx_textinput_search"
|
||||||
|
@ -216,16 +230,21 @@ export const AddExistingToSpace: React.FC<IAddExistingToSpaceProps> = ({
|
||||||
{ rooms.length > 0 ? (
|
{ rooms.length > 0 ? (
|
||||||
<div className="mx_AddExistingToSpace_section">
|
<div className="mx_AddExistingToSpace_section">
|
||||||
<h3>{ _t("Rooms") }</h3>
|
<h3>{ _t("Rooms") }</h3>
|
||||||
{ rooms.map(room => {
|
<TruncatedList
|
||||||
return <Entry
|
truncateAt={truncateAt}
|
||||||
|
createOverflowElement={overflowTile}
|
||||||
|
getChildren={(start, end) => rooms.slice(start, end).map(room =>
|
||||||
|
<Entry
|
||||||
key={room.roomId}
|
key={room.roomId}
|
||||||
room={room}
|
room={room}
|
||||||
checked={selectedToAdd.has(room)}
|
checked={selectedToAdd.has(room)}
|
||||||
onChange={onChange ? (checked) => {
|
onChange={onChange ? (checked) => {
|
||||||
onChange(checked, room);
|
onChange(checked, room);
|
||||||
} : null}
|
} : null}
|
||||||
/>;
|
/>,
|
||||||
}) }
|
)}
|
||||||
|
getChildCount={() => rooms.length}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : undefined }
|
) : undefined }
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,9 @@ import NotificationBadge from "../rooms/NotificationBadge";
|
||||||
import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks";
|
import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks";
|
||||||
import { sortRooms } from "../../../stores/room-list/algorithms/tag-sorting/RecentAlgorithm";
|
import { sortRooms } from "../../../stores/room-list/algorithms/tag-sorting/RecentAlgorithm";
|
||||||
import QueryMatcher from "../../../autocomplete/QueryMatcher";
|
import QueryMatcher from "../../../autocomplete/QueryMatcher";
|
||||||
|
import TruncatedList from "../elements/TruncatedList";
|
||||||
|
import EntityTile from "../rooms/EntityTile";
|
||||||
|
import BaseAvatar from "../avatars/BaseAvatar";
|
||||||
|
|
||||||
const AVATAR_SIZE = 30;
|
const AVATAR_SIZE = 30;
|
||||||
|
|
||||||
|
@ -196,6 +199,17 @@ const ForwardDialog: React.FC<IProps> = ({ matrixClient: cli, event, permalinkCr
|
||||||
}).match(lcQuery);
|
}).match(lcQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const [truncateAt, setTruncateAt] = useState(20);
|
||||||
|
function overflowTile(overflowCount, totalCount) {
|
||||||
|
const text = _t("and %(count)s others...", { count: overflowCount });
|
||||||
|
return (
|
||||||
|
<EntityTile className="mx_EntityTile_ellipsis" avatarJsx={
|
||||||
|
<BaseAvatar url={require("../../../../res/img/ellipsis.svg")} name="..." width={36} height={36} />
|
||||||
|
} name={text} presenceState="online" suppressOnHover={true}
|
||||||
|
onClick={() => setTruncateAt(totalCount)} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return <BaseDialog
|
return <BaseDialog
|
||||||
title={_t("Forward message")}
|
title={_t("Forward message")}
|
||||||
className="mx_ForwardDialog"
|
className="mx_ForwardDialog"
|
||||||
|
@ -228,7 +242,10 @@ const ForwardDialog: React.FC<IProps> = ({ matrixClient: cli, event, permalinkCr
|
||||||
<AutoHideScrollbar className="mx_ForwardList_content">
|
<AutoHideScrollbar className="mx_ForwardList_content">
|
||||||
{ rooms.length > 0 ? (
|
{ rooms.length > 0 ? (
|
||||||
<div className="mx_ForwardList_results">
|
<div className="mx_ForwardList_results">
|
||||||
{ rooms.map(room =>
|
<TruncatedList
|
||||||
|
truncateAt={truncateAt}
|
||||||
|
createOverflowElement={overflowTile}
|
||||||
|
getChildren={(start, end) => rooms.slice(start, end).map(room =>
|
||||||
<Entry
|
<Entry
|
||||||
key={room.roomId}
|
key={room.roomId}
|
||||||
room={room}
|
room={room}
|
||||||
|
@ -236,7 +253,9 @@ const ForwardDialog: React.FC<IProps> = ({ matrixClient: cli, event, permalinkCr
|
||||||
matrixClient={cli}
|
matrixClient={cli}
|
||||||
onFinished={onFinished}
|
onFinished={onFinished}
|
||||||
/>,
|
/>,
|
||||||
) }
|
)}
|
||||||
|
getChildCount={() => rooms.length}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : <span className="mx_ForwardList_noResults">
|
) : <span className="mx_ForwardList_noResults">
|
||||||
{ _t("No results") }
|
{ _t("No results") }
|
||||||
|
|
|
@ -16,31 +16,29 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||||
|
|
||||||
@replaceableComponent("views.elements.TruncatedList")
|
interface IProps {
|
||||||
export default class TruncatedList extends React.Component {
|
|
||||||
static propTypes = {
|
|
||||||
// The number of elements to show before truncating. If negative, no truncation is done.
|
// The number of elements to show before truncating. If negative, no truncation is done.
|
||||||
truncateAt: PropTypes.number,
|
truncateAt?: number;
|
||||||
// The className to apply to the wrapping div
|
// The className to apply to the wrapping div
|
||||||
className: PropTypes.string,
|
className?: string;
|
||||||
// A function that returns the children to be rendered into the element.
|
// A function that returns the children to be rendered into the element.
|
||||||
// function getChildren(start: number, end: number): Array<React.Node>
|
|
||||||
// The start element is included, the end is not (as in `slice`).
|
// The start element is included, the end is not (as in `slice`).
|
||||||
// If omitted, the React child elements will be used. This parameter can be used
|
// If omitted, the React child elements will be used. This parameter can be used
|
||||||
// to avoid creating unnecessary React elements.
|
// to avoid creating unnecessary React elements.
|
||||||
getChildren: PropTypes.func,
|
getChildren?: (start: number, end: number) => Array<React.ReactNode>;
|
||||||
// A function that should return the total number of child element available.
|
// A function that should return the total number of child element available.
|
||||||
// Required if getChildren is supplied.
|
// Required if getChildren is supplied.
|
||||||
getChildCount: PropTypes.func,
|
getChildCount?: () => number;
|
||||||
// A function which will be invoked when an overflow element is required.
|
// A function which will be invoked when an overflow element is required.
|
||||||
// This will be inserted after the children.
|
// This will be inserted after the children.
|
||||||
createOverflowElement: PropTypes.func,
|
createOverflowElement?: (overflowCount: number, totalCount: number) => React.ReactNode;
|
||||||
};
|
}
|
||||||
|
|
||||||
|
@replaceableComponent("views.elements.TruncatedList")
|
||||||
|
export default class TruncatedList extends React.Component<IProps> {
|
||||||
static defaultProps ={
|
static defaultProps ={
|
||||||
truncateAt: 2,
|
truncateAt: 2,
|
||||||
createOverflowElement(overflowCount, totalCount) {
|
createOverflowElement(overflowCount, totalCount) {
|
||||||
|
@ -50,7 +48,7 @@ export default class TruncatedList extends React.Component {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
_getChildren(start, end) {
|
private getChildren(start: number, end: number): Array<React.ReactNode> {
|
||||||
if (this.props.getChildren && this.props.getChildCount) {
|
if (this.props.getChildren && this.props.getChildCount) {
|
||||||
return this.props.getChildren(start, end);
|
return this.props.getChildren(start, end);
|
||||||
} else {
|
} else {
|
||||||
|
@ -63,7 +61,7 @@ export default class TruncatedList extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_getChildCount() {
|
private getChildCount(): number {
|
||||||
if (this.props.getChildren && this.props.getChildCount) {
|
if (this.props.getChildren && this.props.getChildCount) {
|
||||||
return this.props.getChildCount();
|
return this.props.getChildCount();
|
||||||
} else {
|
} else {
|
||||||
|
@ -73,10 +71,10 @@ export default class TruncatedList extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
public render() {
|
||||||
let overflowNode = null;
|
let overflowNode = null;
|
||||||
|
|
||||||
const totalChildren = this._getChildCount();
|
const totalChildren = this.getChildCount();
|
||||||
let upperBound = totalChildren;
|
let upperBound = totalChildren;
|
||||||
if (this.props.truncateAt >= 0) {
|
if (this.props.truncateAt >= 0) {
|
||||||
const overflowCount = totalChildren - this.props.truncateAt;
|
const overflowCount = totalChildren - this.props.truncateAt;
|
||||||
|
@ -87,7 +85,7 @@ export default class TruncatedList extends React.Component {
|
||||||
upperBound = this.props.truncateAt;
|
upperBound = this.props.truncateAt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const childNodes = this._getChildren(0, upperBound);
|
const childNodes = this.getChildren(0, upperBound);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={this.props.className}>
|
<div className={this.props.className}>
|
Loading…
Reference in New Issue