Show sharer preview for matrix.to links
This commit is contained in:
parent
85fab36308
commit
74b790927e
5 changed files with 128 additions and 62 deletions
|
@ -19,4 +19,8 @@ limitations under the License.
|
|||
border-radius: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,10 +20,11 @@ import { getEvent, client } from 'matrix-cypher';
|
|||
import { RoomPreviewWithTopic } from './RoomPreview';
|
||||
import InviteTile from './InviteTile';
|
||||
import { SafeLink, LinkKind } from '../parser/types';
|
||||
import UserPreview from './UserPreview';
|
||||
import UserPreview, { WrappedInviterPreview } from './UserPreview';
|
||||
import EventPreview from './EventPreview';
|
||||
import HomeserverOptions from './HomeserverOptions';
|
||||
import DefaultPreview from './DefaultPreview';
|
||||
import Toggle from './Toggle';
|
||||
import { clientMap } from '../clients';
|
||||
import {
|
||||
getRoomFromId,
|
||||
|
@ -32,12 +33,7 @@ import {
|
|||
getUser,
|
||||
} from '../utils/cypher-wrapper';
|
||||
import { ClientContext } from '../contexts/ClientContext';
|
||||
import HSContext, {
|
||||
TempHSContext,
|
||||
HSOptions,
|
||||
State as HSState,
|
||||
} from '../contexts/HSContext';
|
||||
import Toggle from './Toggle';
|
||||
import useHSs from '../utils/getHS';
|
||||
|
||||
interface IProps {
|
||||
link: SafeLink;
|
||||
|
@ -118,32 +114,14 @@ const Preview: React.FC<PreviewProps> = ({ link, client }: PreviewProps) => {
|
|||
return content;
|
||||
};
|
||||
|
||||
function selectedClient(link: SafeLink, hsOptions: HSState): string[] {
|
||||
switch (hsOptions.option) {
|
||||
case HSOptions.Unset:
|
||||
return [];
|
||||
case HSOptions.None:
|
||||
return [];
|
||||
case HSOptions.TrustedHSOnly:
|
||||
return [hsOptions.hs];
|
||||
case HSOptions.Any:
|
||||
return [
|
||||
'https://' + link.identifier.split(':')[1],
|
||||
...link.arguments.vias,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
const LinkPreview: React.FC<IProps> = ({ link }: IProps) => {
|
||||
let content: JSX.Element;
|
||||
const [showHSOptions, setShowHSOPtions] = useState(false);
|
||||
const [hsOptions] = useContext(HSContext);
|
||||
const [tempHSState] = useContext(TempHSContext);
|
||||
|
||||
if (
|
||||
hsOptions.option === HSOptions.Unset &&
|
||||
tempHSState.option === HSOptions.Unset
|
||||
) {
|
||||
const hses = useHSs(link);
|
||||
console.log(hses);
|
||||
|
||||
if (!hses) {
|
||||
content = (
|
||||
<>
|
||||
<DefaultPreview link={link} />
|
||||
|
@ -164,11 +142,7 @@ const LinkPreview: React.FC<IProps> = ({ link }: IProps) => {
|
|||
);
|
||||
}
|
||||
} else {
|
||||
const clients =
|
||||
tempHSState.option !== HSOptions.Unset
|
||||
? selectedClient(link, tempHSState)
|
||||
: selectedClient(link, hsOptions);
|
||||
content = <Preview link={link} client={clients[0]} />;
|
||||
content = <Preview link={link} client={hses[0]} />;
|
||||
}
|
||||
|
||||
const [{ clientId }] = useContext(ClientContext);
|
||||
|
@ -182,8 +156,20 @@ const LinkPreview: React.FC<IProps> = ({ link }: IProps) => {
|
|||
|
||||
const client = displayClientId ? clientMap[displayClientId] : null;
|
||||
|
||||
const sharer = link.arguments.sharer ? (
|
||||
<WrappedInviterPreview
|
||||
link={{
|
||||
kind: LinkKind.UserId,
|
||||
identifier: link.arguments.sharer,
|
||||
arguments: { vias: [] },
|
||||
originalLink: '',
|
||||
}}
|
||||
/>
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<InviteTile client={client} link={link}>
|
||||
{sharer}
|
||||
{content}
|
||||
</InviteTile>
|
||||
);
|
||||
|
|
|
@ -14,10 +14,13 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { User } from 'matrix-cypher';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { client, User, getUserDetails } from 'matrix-cypher';
|
||||
import icon from '../imgs/chat-icon.svg';
|
||||
|
||||
import { UserAvatar } from './Avatar';
|
||||
import Avatar, { UserAvatar } from './Avatar';
|
||||
import useHSs from '../utils/getHS';
|
||||
import { UserId } from '../parser/types';
|
||||
|
||||
import './UserPreview.scss';
|
||||
|
||||
|
@ -37,14 +40,49 @@ const UserPreview: React.FC<IProps> = ({ user, userId }: IProps) => (
|
|||
|
||||
export default UserPreview;
|
||||
|
||||
export const InviterPreview: React.FC<IProps> = ({ user, userId }: IProps) => (
|
||||
<div className="miniUserPreview">
|
||||
<div>
|
||||
<h1>
|
||||
Invited by <b>{user.displayname}</b>
|
||||
</h1>
|
||||
<p>{userId}</p>
|
||||
</div>
|
||||
interface InviterPreviewProps {
|
||||
user?: User;
|
||||
userId: string;
|
||||
}
|
||||
|
||||
export const InviterPreview: React.FC<InviterPreviewProps> = ({
|
||||
user,
|
||||
userId,
|
||||
}: InviterPreviewProps) => {
|
||||
const avatar = user ? (
|
||||
<UserAvatar user={user} userId={userId} />
|
||||
</div>
|
||||
);
|
||||
) : (
|
||||
<Avatar label={`Placeholder icon for ${userId}`} avatarUrl={icon} />
|
||||
);
|
||||
return (
|
||||
<div className="miniUserPreview">
|
||||
<div>
|
||||
<h1>
|
||||
Invited by <b>{user ? user.displayname : userId}</b>
|
||||
</h1>
|
||||
{user ? <p>{userId}</p> : null}
|
||||
</div>
|
||||
{avatar}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
interface WrappedInviterProps {
|
||||
link: UserId;
|
||||
}
|
||||
|
||||
export const WrappedInviterPreview: React.FC<WrappedInviterProps> = ({
|
||||
link,
|
||||
}: WrappedInviterProps) => {
|
||||
const [user, setUser] = useState<User | undefined>(undefined);
|
||||
const hss = useHSs(link);
|
||||
useEffect(() => {
|
||||
if (hss) {
|
||||
client(hss[0])
|
||||
.then((c) => getUserDetails(c, link.identifier))
|
||||
.then(setUser)
|
||||
.catch((x) => console.log("couldn't fetch user preview", x));
|
||||
}
|
||||
}, [hss, link]);
|
||||
return <InviterPreview user={user} userId={link.identifier} />;
|
||||
};
|
||||
|
|
|
@ -29,17 +29,12 @@ export enum HSOptions {
|
|||
TrustedHSOnly = 'TRUSTED_CLIENT_ONLY',
|
||||
// Matrix.to may contact any homeserver it requires
|
||||
Any = 'ANY',
|
||||
// Matrix.to may not contact any homeservers
|
||||
None = 'NONE',
|
||||
}
|
||||
|
||||
const STATE_SCHEMA = union([
|
||||
object({
|
||||
option: literal(HSOptions.Unset),
|
||||
}),
|
||||
object({
|
||||
option: literal(HSOptions.None),
|
||||
}),
|
||||
object({
|
||||
option: literal(HSOptions.Any),
|
||||
}),
|
||||
|
@ -55,7 +50,6 @@ export type State = TypeOf<typeof STATE_SCHEMA>;
|
|||
export enum ActionType {
|
||||
SetHS = 'SET_HS',
|
||||
SetAny = 'SET_ANY',
|
||||
SetNone = 'SET_NONE',
|
||||
}
|
||||
|
||||
export interface SetHS {
|
||||
|
@ -67,11 +61,7 @@ export interface SetAny {
|
|||
action: ActionType.SetAny;
|
||||
}
|
||||
|
||||
export interface SetNone {
|
||||
action: ActionType.SetNone;
|
||||
}
|
||||
|
||||
export type Action = SetHS | SetAny | SetNone;
|
||||
export type Action = SetHS | SetAny;
|
||||
|
||||
export const INITIAL_STATE: State = {
|
||||
option: HSOptions.Unset,
|
||||
|
@ -81,10 +71,6 @@ export const unpersistedReducer = (state: State, action: Action): State => {
|
|||
console.log('reducing');
|
||||
console.log(action);
|
||||
switch (action.action) {
|
||||
case ActionType.SetNone:
|
||||
return {
|
||||
option: HSOptions.None,
|
||||
};
|
||||
case ActionType.SetAny:
|
||||
return {
|
||||
option: HSOptions.Any,
|
||||
|
|
52
src/utils/getHS.ts
Normal file
52
src/utils/getHS.ts
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { useContext } from 'react';
|
||||
import HSContext, {
|
||||
TempHSContext,
|
||||
State,
|
||||
HSOptions,
|
||||
} from '../contexts/HSContext';
|
||||
import { SafeLink } from '../parser/types';
|
||||
|
||||
function selectedClient(link: SafeLink, hsOptions: State): string[] {
|
||||
switch (hsOptions.option) {
|
||||
case HSOptions.Unset:
|
||||
return [];
|
||||
case HSOptions.TrustedHSOnly:
|
||||
return [hsOptions.hs];
|
||||
case HSOptions.Any:
|
||||
return [
|
||||
...link.identifier
|
||||
.split('/')
|
||||
.map((i) => 'https://' + i.split(':')[1]),
|
||||
...link.arguments.vias,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
export default function useHSs(link: SafeLink): string[] {
|
||||
const [HSState] = useContext(HSContext);
|
||||
const [TempHSState] = useContext(TempHSContext);
|
||||
|
||||
if (HSState.option !== HSOptions.Unset) {
|
||||
return selectedClient(link, HSState);
|
||||
} else if (TempHSState.option !== HSOptions.Unset) {
|
||||
return selectedClient(link, TempHSState);
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue