mirror of https://github.com/vector-im/riot-web
				
				
				
			only consider valid & loaded url previews for show N more prompt
							parent
							
								
									829169ec87
								
							
						
					
					
						commit
						e3e7d41d5c
					
				| 
						 | 
				
			
			@ -14,43 +14,57 @@ See the License for the specific language governing permissions and
 | 
			
		|||
limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
import React, { useEffect } from "react";
 | 
			
		||||
import React, { useContext, useEffect } from "react";
 | 
			
		||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
 | 
			
		||||
import { IPreviewUrlResponse } from "matrix-js-sdk/src/client";
 | 
			
		||||
 | 
			
		||||
import { useStateToggle } from "../../../hooks/useStateToggle";
 | 
			
		||||
import LinkPreviewWidget from "./LinkPreviewWidget";
 | 
			
		||||
import AccessibleButton from "../elements/AccessibleButton";
 | 
			
		||||
import { _t } from "../../../languageHandler";
 | 
			
		||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
 | 
			
		||||
import { useAsyncMemo } from "../../../hooks/useAsyncMemo";
 | 
			
		||||
 | 
			
		||||
const INITIAL_NUM_PREVIEWS = 2;
 | 
			
		||||
 | 
			
		||||
interface IProps {
 | 
			
		||||
    links: string[]; // the URLs to be previewed
 | 
			
		||||
    mxEvent: MatrixEvent; // the Event associated with the preview
 | 
			
		||||
    onCancelClick?(): void; // called when the preview's cancel ('hide') button is clicked
 | 
			
		||||
    onHeightChanged?(): void; // called when the preview's contents has loaded
 | 
			
		||||
    onCancelClick(): void; // called when the preview's cancel ('hide') button is clicked
 | 
			
		||||
    onHeightChanged(): void; // called when the preview's contents has loaded
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const LinkPreviewGroup: React.FC<IProps> = ({ links, mxEvent, onCancelClick, onHeightChanged }) => {
 | 
			
		||||
    const cli = useContext(MatrixClientContext);
 | 
			
		||||
    const [expanded, toggleExpanded] = useStateToggle();
 | 
			
		||||
 | 
			
		||||
    const ts = mxEvent.getTs();
 | 
			
		||||
    const previews = useAsyncMemo<[string, IPreviewUrlResponse][]>(async () => {
 | 
			
		||||
        return Promise.all<[string, IPreviewUrlResponse] | void>(links.map(link => {
 | 
			
		||||
            return cli.getUrlPreview(link, ts).then(preview => [link, preview], error => {
 | 
			
		||||
                console.error("Failed to get URL preview: " + error);
 | 
			
		||||
            });
 | 
			
		||||
        })).then(a => a.filter(Boolean)) as Promise<[string, IPreviewUrlResponse][]>;
 | 
			
		||||
    }, [links, ts], []);
 | 
			
		||||
 | 
			
		||||
    useEffect(() => {
 | 
			
		||||
        onHeightChanged();
 | 
			
		||||
    }, [onHeightChanged, expanded]);
 | 
			
		||||
    }, [onHeightChanged, expanded, previews]);
 | 
			
		||||
 | 
			
		||||
    const shownLinks = expanded ? links : links.slice(0, INITIAL_NUM_PREVIEWS);
 | 
			
		||||
    const showPreviews = expanded ? previews : previews.slice(0, INITIAL_NUM_PREVIEWS);
 | 
			
		||||
 | 
			
		||||
    let toggleButton;
 | 
			
		||||
    if (links.length > INITIAL_NUM_PREVIEWS) {
 | 
			
		||||
    let toggleButton: JSX.Element;
 | 
			
		||||
    if (previews.length > INITIAL_NUM_PREVIEWS) {
 | 
			
		||||
        toggleButton = <AccessibleButton onClick={toggleExpanded}>
 | 
			
		||||
            { expanded
 | 
			
		||||
                ? _t("Collapse")
 | 
			
		||||
                : _t("Show %(count)s other previews", { count: links.length - shownLinks.length }) }
 | 
			
		||||
                : _t("Show %(count)s other previews", { count: previews.length - showPreviews.length }) }
 | 
			
		||||
        </AccessibleButton>;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return <div className="mx_LinkPreviewGroup">
 | 
			
		||||
        { shownLinks.map((link, i) => (
 | 
			
		||||
            <LinkPreviewWidget key={link} link={link} mxEvent={mxEvent} onHeightChanged={onHeightChanged}>
 | 
			
		||||
        { showPreviews.map(([link, preview], i) => (
 | 
			
		||||
            <LinkPreviewWidget key={link} link={link} preview={preview} mxEvent={mxEvent}>
 | 
			
		||||
                { i === 0 ? (
 | 
			
		||||
                    <AccessibleButton
 | 
			
		||||
                        className="mx_LinkPreviewGroup_hide"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,7 +21,6 @@ import { IPreviewUrlResponse } from 'matrix-js-sdk/src/client';
 | 
			
		|||
 | 
			
		||||
import { linkifyElement } from '../../../HtmlUtils';
 | 
			
		||||
import SettingsStore from "../../../settings/SettingsStore";
 | 
			
		||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
 | 
			
		||||
import Modal from "../../../Modal";
 | 
			
		||||
import * as ImageUtils from "../../../ImageUtils";
 | 
			
		||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
 | 
			
		||||
| 
						 | 
				
			
			@ -29,37 +28,15 @@ import { mediaFromMxc } from "../../../customisations/Media";
 | 
			
		|||
import ImageView from '../elements/ImageView';
 | 
			
		||||
 | 
			
		||||
interface IProps {
 | 
			
		||||
    link: string; // the URL being previewed
 | 
			
		||||
    link: string;
 | 
			
		||||
    preview: IPreviewUrlResponse;
 | 
			
		||||
    mxEvent: MatrixEvent; // the Event associated with the preview
 | 
			
		||||
    onHeightChanged(): void; // called when the preview's contents has loaded
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface IState {
 | 
			
		||||
    preview?: IPreviewUrlResponse;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@replaceableComponent("views.rooms.LinkPreviewWidget")
 | 
			
		||||
export default class LinkPreviewWidget extends React.Component<IProps, IState> {
 | 
			
		||||
    private unmounted = false;
 | 
			
		||||
export default class LinkPreviewWidget extends React.Component<IProps> {
 | 
			
		||||
    private readonly description = createRef<HTMLDivElement>();
 | 
			
		||||
 | 
			
		||||
    constructor(props) {
 | 
			
		||||
        super(props);
 | 
			
		||||
 | 
			
		||||
        this.state = {
 | 
			
		||||
            preview: null,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        MatrixClientPeg.get().getUrlPreview(this.props.link, this.props.mxEvent.getTs()).then((preview) => {
 | 
			
		||||
            if (this.unmounted) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            this.setState({ preview }, this.props.onHeightChanged);
 | 
			
		||||
        }, (error) => {
 | 
			
		||||
            console.error("Failed to get URL preview: " + error);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    componentDidMount() {
 | 
			
		||||
        if (this.description.current) {
 | 
			
		||||
            linkifyElement(this.description.current);
 | 
			
		||||
| 
						 | 
				
			
			@ -72,12 +49,8 @@ export default class LinkPreviewWidget extends React.Component<IProps, IState> {
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    componentWillUnmount() {
 | 
			
		||||
        this.unmounted = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private onImageClick = ev => {
 | 
			
		||||
        const p = this.state.preview;
 | 
			
		||||
        const p = this.props.preview;
 | 
			
		||||
        if (ev.button != 0 || ev.metaKey) return;
 | 
			
		||||
        ev.preventDefault();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -99,7 +72,7 @@ export default class LinkPreviewWidget extends React.Component<IProps, IState> {
 | 
			
		|||
    };
 | 
			
		||||
 | 
			
		||||
    render() {
 | 
			
		||||
        const p = this.state.preview;
 | 
			
		||||
        const p = this.props.preview;
 | 
			
		||||
        if (!p || Object.keys(p).length === 0) {
 | 
			
		||||
            return <div />;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue