Add room list avatar option & youtube embed player option
This commit is contained in:
parent
8ea2b0b63b
commit
5c81ba994c
7 changed files with 185 additions and 3 deletions
|
@ -15,6 +15,7 @@ import ExternalSVG from '../../../../public/res/ic/outlined/external.svg';
|
|||
import PlaySVG from '../../../../public/res/ic/outlined/play.svg';
|
||||
|
||||
import { getBlobSafeMimeType } from '../../../util/mimetypes';
|
||||
import initMatrix from '../../../client/initMatrix';
|
||||
|
||||
async function getDecryptedBlob(response, type, decryptData) {
|
||||
const arrayBuffer = await response.arrayBuffer();
|
||||
|
@ -361,6 +362,83 @@ Video.propTypes = {
|
|||
blurhash: PropTypes.string,
|
||||
};
|
||||
|
||||
export {
|
||||
File, Image, Sticker, Audio, Video,
|
||||
function YoutubeEmbed({ link }) {
|
||||
const url = new URL(link);
|
||||
|
||||
const [urlPreviewInfo, setUrlPreviewInfo] = useState(null);
|
||||
const [videoStarted, setVideoStarted] = useState(false);
|
||||
|
||||
const mx = initMatrix.matrixClient;
|
||||
|
||||
const handlePlayVideo = () => {
|
||||
setVideoStarted(true);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
let unmounted = false;
|
||||
|
||||
async function getThumbnail() {
|
||||
const info = await mx.getUrlPreview(link, 0);
|
||||
if (unmounted) return;
|
||||
|
||||
setUrlPreviewInfo(info);
|
||||
}
|
||||
|
||||
getThumbnail();
|
||||
|
||||
return () => {
|
||||
unmounted = true;
|
||||
};
|
||||
});
|
||||
|
||||
let embedURL = `https://www.youtube-nocookie.com/embed/${url.searchParams.get('v')}?autoplay=1`;
|
||||
if (url.searchParams.has('t')) {
|
||||
embedURL += `&start=${url.searchParams.get('t')}`;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="file-container">
|
||||
{urlPreviewInfo !== null && (
|
||||
<div>
|
||||
|
||||
<div className="file-header">
|
||||
<Text className="file-name" variant="b3">{`Youtube - ${urlPreviewInfo['og:title']}`}</Text>
|
||||
|
||||
<IconButton
|
||||
size="extra-small"
|
||||
tooltip="Open in new tab"
|
||||
src={ExternalSVG}
|
||||
onClick={() => window.open(link)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="video-container"
|
||||
>
|
||||
{!videoStarted && <img src={mx.mxcUrlToHttp(urlPreviewInfo['og:image'])} alt="Youtube thumbnail" />}
|
||||
{!videoStarted && <IconButton onClick={handlePlayVideo} tooltip="Play video" src={PlaySVG} />}
|
||||
|
||||
{videoStarted && (
|
||||
<iframe
|
||||
src={embedURL}
|
||||
title="YouTube video player"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowFullScreen
|
||||
/>
|
||||
)}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
);
|
||||
}
|
||||
YoutubeEmbed.propTypes = {
|
||||
link: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export {
|
||||
File, Image, Sticker, Audio, Video, YoutubeEmbed,
|
||||
};
|
||||
|
|
|
@ -29,6 +29,7 @@ import IconButton from '../../atoms/button/IconButton';
|
|||
import Time from '../../atoms/time/Time';
|
||||
import ContextMenu, { MenuHeader, MenuItem, MenuBorder } from '../../atoms/context-menu/ContextMenu';
|
||||
import * as Media from '../media/Media';
|
||||
import settings from '../../../client/state/settings';
|
||||
|
||||
import ReplyArrowIC from '../../../../public/res/ic/outlined/reply-arrow.svg';
|
||||
import EmojiAddIC from '../../../../public/res/ic/outlined/emoji-add.svg';
|
||||
|
@ -41,6 +42,7 @@ import BinIC from '../../../../public/res/ic/outlined/bin.svg';
|
|||
import { confirmDialog } from '../confirm-dialog/ConfirmDialog';
|
||||
import { getBlobSafeMimeType } from '../../../util/mimetypes';
|
||||
import { html, plain } from '../../../util/markdown';
|
||||
import { YoutubeEmbed } from '../media/Media';
|
||||
|
||||
function PlaceholderMessage() {
|
||||
return (
|
||||
|
@ -716,6 +718,10 @@ function getEditedBody(editedMEvent) {
|
|||
return [parsedContent.body, isCustomHTML, newContent.formatted_body ?? null];
|
||||
}
|
||||
|
||||
function findYoutubeLinks(body) {
|
||||
return [...new Set(body.match(/https?:\/\/(?:www\.)?(?:youtube\.com\/watch\?v=|youtu\.be\/)[^ \n]+/g))] ?? [];
|
||||
}
|
||||
|
||||
function Message({
|
||||
mEvent, isBodyOnly, roomTimeline,
|
||||
focus, fullTime, isEdit, setEdit, cancelEdit,
|
||||
|
@ -801,6 +807,9 @@ function Message({
|
|||
isEdited={isEdited}
|
||||
/>
|
||||
)}
|
||||
{settings.showYoutubeEmbedPlayer && findYoutubeLinks(body).map((link) => (
|
||||
<YoutubeEmbed key={link} link={link} />
|
||||
))}
|
||||
{isEdit && (
|
||||
<MessageEdit
|
||||
body={(customHTML
|
||||
|
|
|
@ -5,10 +5,12 @@ import './RoomSelector.scss';
|
|||
import { twemojify } from '../../../util/twemojify';
|
||||
import colorMXID from '../../../util/colorMXID';
|
||||
|
||||
import initMatrix from '../../../client/initMatrix';
|
||||
import Text from '../../atoms/text/Text';
|
||||
import Avatar from '../../atoms/avatar/Avatar';
|
||||
import NotificationBadge from '../../atoms/badge/NotificationBadge';
|
||||
import { blurOnBubbling } from '../../atoms/button/script';
|
||||
import settings from '../../../client/state/settings';
|
||||
|
||||
function RoomSelectorWrapper({
|
||||
isSelected, isMuted, isUnread, onClick,
|
||||
|
@ -54,6 +56,13 @@ function RoomSelector({
|
|||
isSelected, isMuted, isUnread, notificationCount, isAlert,
|
||||
options, onClick, onContextMenu,
|
||||
}) {
|
||||
let avatarSrc;
|
||||
if (settings.showRoomListAvatar) {
|
||||
const mx = initMatrix.matrixClient;
|
||||
const room = mx.getRoom(roomId);
|
||||
avatarSrc = room.getAvatarUrl(mx.baseUrl, 24, 24, 'crop');
|
||||
}
|
||||
|
||||
return (
|
||||
<RoomSelectorWrapper
|
||||
isSelected={isSelected}
|
||||
|
@ -61,6 +70,7 @@ function RoomSelector({
|
|||
isUnread={isUnread}
|
||||
content={(
|
||||
<>
|
||||
{!settings.showRoomListAvatar && (
|
||||
<Avatar
|
||||
text={name}
|
||||
bgColor={colorMXID(roomId)}
|
||||
|
@ -69,6 +79,15 @@ function RoomSelector({
|
|||
iconSrc={iconSrc}
|
||||
size="extra-small"
|
||||
/>
|
||||
)}
|
||||
{settings.showRoomListAvatar && (
|
||||
<Avatar
|
||||
text={name}
|
||||
bgColor={colorMXID(roomId)}
|
||||
imageSrc={avatarSrc}
|
||||
size="extra-small"
|
||||
/>
|
||||
)}
|
||||
<Text variant="b1" weight={isUnread ? 'medium' : 'normal'}>
|
||||
{twemojify(name)}
|
||||
{parentName && (
|
||||
|
|
|
@ -7,7 +7,7 @@ import settings from '../../../client/state/settings';
|
|||
import navigation from '../../../client/state/navigation';
|
||||
import {
|
||||
toggleSystemTheme, toggleMarkdown, toggleMembershipEvents, toggleNickAvatarEvents,
|
||||
toggleNotifications, toggleNotificationSounds,
|
||||
toggleNotifications, toggleNotificationSounds, toggleShowRoomListAvatar, toggleShowYoutubeEmbedPlayer,
|
||||
} from '../../../client/action/settings';
|
||||
import { usePermission } from '../../hooks/usePermission';
|
||||
|
||||
|
@ -80,6 +80,26 @@ function AppearanceSection() {
|
|||
/>
|
||||
)}
|
||||
/>
|
||||
<SettingTile
|
||||
title="Show room-list avatar"
|
||||
options={(
|
||||
<Toggle
|
||||
isActive={settings.showRoomListAvatar}
|
||||
onToggle={() => { toggleShowRoomListAvatar(); updateState({}); }}
|
||||
/>
|
||||
)}
|
||||
content={<Text variant="b3">Will show room avatars in the room list.</Text>}
|
||||
/>
|
||||
<SettingTile
|
||||
title="Show Youtube embed player"
|
||||
options={(
|
||||
<Toggle
|
||||
isActive={settings.showYoutubeEmbedPlayer}
|
||||
onToggle={() => { toggleShowYoutubeEmbedPlayer(); updateState({}); }}
|
||||
/>
|
||||
)}
|
||||
content={<Text variant="b3">Will show a youtube embed player for youtube links.</Text>}
|
||||
/>
|
||||
</div>
|
||||
<div className="settings-appearance__card">
|
||||
<MenuHeader>Room messages</MenuHeader>
|
||||
|
|
|
@ -42,3 +42,15 @@ export function toggleNotificationSounds() {
|
|||
type: cons.actions.settings.TOGGLE_NOTIFICATION_SOUNDS,
|
||||
});
|
||||
}
|
||||
|
||||
export function toggleShowRoomListAvatar() {
|
||||
appDispatcher.dispatch({
|
||||
type: cons.actions.settings.TOGGLE_SHOW_ROOM_LIST_AVATAR,
|
||||
});
|
||||
}
|
||||
|
||||
export function toggleShowYoutubeEmbedPlayer() {
|
||||
appDispatcher.dispatch({
|
||||
type: cons.actions.settings.TOGGLE_SHOW_YOUTUBE_EMBED_PLAYER,
|
||||
})
|
||||
}
|
|
@ -72,6 +72,8 @@ const cons = {
|
|||
TOGGLE_NICKAVATAR_EVENT: 'TOGGLE_NICKAVATAR_EVENT',
|
||||
TOGGLE_NOTIFICATIONS: 'TOGGLE_NOTIFICATIONS',
|
||||
TOGGLE_NOTIFICATION_SOUNDS: 'TOGGLE_NOTIFICATION_SOUNDS',
|
||||
TOGGLE_SHOW_ROOM_LIST_AVATAR: 'TOGGLE_SHOW_ROOM_LIST_AVATAR',
|
||||
TOGGLE_SHOW_YOUTUBE_EMBED_PLAYER: 'TOGGLE_SHOW_YOUTUBE_EMBED_PLAYER',
|
||||
},
|
||||
},
|
||||
events: {
|
||||
|
@ -144,6 +146,8 @@ const cons = {
|
|||
NICKAVATAR_EVENTS_TOGGLED: 'NICKAVATAR_EVENTS_TOGGLED',
|
||||
NOTIFICATIONS_TOGGLED: 'NOTIFICATIONS_TOGGLED',
|
||||
NOTIFICATION_SOUNDS_TOGGLED: 'NOTIFICATION_SOUNDS_TOGGLED',
|
||||
SHOW_ROOM_LIST_AVATAR_TOGGLED: 'SHOW_ROOM_LIST_AVATAR_TOGGLED',
|
||||
SHOW_YOUTUBE_EMBED_PLAYER_TOGGLED: 'SHOW_YOUTUBE_EMBED_PLAYER_TOGGLED',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -30,6 +30,8 @@ class Settings extends EventEmitter {
|
|||
this.hideNickAvatarEvents = this.getHideNickAvatarEvents();
|
||||
this._showNotifications = this.getShowNotifications();
|
||||
this.isNotificationSounds = this.getIsNotificationSounds();
|
||||
this.showRoomListAvatar = this.getShowRoomListAvatar();
|
||||
this.showYoutubeEmbedPlayer = this.getShowYoutubeEmbedPlayer();
|
||||
|
||||
this.isTouchScreenDevice = ('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0);
|
||||
}
|
||||
|
@ -147,6 +149,38 @@ class Settings extends EventEmitter {
|
|||
return settings.isNotificationSounds;
|
||||
}
|
||||
|
||||
toggleShowRoomListAvatar() {
|
||||
this.showRoomListAvatar = !this.showRoomListAvatar;
|
||||
setSettings('showRoomListAvatar', this.showRoomListAvatar);
|
||||
|
||||
this.emit(cons.events.settings.SHOW_ROOM_LIST_AVATAR_TOGGLED, this.showRoomListAvatar);
|
||||
}
|
||||
|
||||
getShowRoomListAvatar() {
|
||||
if (typeof this.showRoomListAvatar === 'boolean') return this.showRoomListAvatar;
|
||||
|
||||
const settings = getSettings();
|
||||
if (settings === null) return false;
|
||||
if (typeof settings.showRoomListAvatar === 'undefined') return false;
|
||||
return settings.showRoomListAvatar;
|
||||
}
|
||||
|
||||
toggleShowYoutubeEmbedPlayer() {
|
||||
this.showYoutubeEmbedPlayer = !this.showYoutubeEmbedPlayer;
|
||||
setSettings('showYoutubeEmbedPlayer', this.showYoutubeEmbedPlayer);
|
||||
|
||||
this.emit(cons.events.settings.SHOW_YOUTUBE_EMBED_PLAYER_TOGGLED, this.showYoutubeEmbedPlayer);
|
||||
}
|
||||
|
||||
getShowYoutubeEmbedPlayer() {
|
||||
if (typeof this.showYoutubeEmbedPlayer === 'boolean') return this.showYoutubeEmbedPlayer;
|
||||
|
||||
const settings = getSettings();
|
||||
if (settings === null) return false;
|
||||
if (typeof settings.showYoutubeEmbedPlayer === 'undefined') return false;
|
||||
return settings.showYoutubeEmbedPlayer;
|
||||
}
|
||||
|
||||
setter(action) {
|
||||
const actions = {
|
||||
[cons.actions.settings.TOGGLE_SYSTEM_THEME]: () => {
|
||||
|
@ -186,6 +220,12 @@ class Settings extends EventEmitter {
|
|||
setSettings('isNotificationSounds', this.isNotificationSounds);
|
||||
this.emit(cons.events.settings.NOTIFICATION_SOUNDS_TOGGLED, this.isNotificationSounds);
|
||||
},
|
||||
[cons.actions.settings.TOGGLE_SHOW_ROOM_LIST_AVATAR]: () => {
|
||||
this.toggleShowRoomListAvatar();
|
||||
},
|
||||
[cons.actions.settings.TOGGLE_SHOW_YOUTUBE_EMBED_PLAYER]: () => {
|
||||
this.toggleShowYoutubeEmbedPlayer();
|
||||
},
|
||||
};
|
||||
|
||||
actions[action.type]?.();
|
||||
|
|
Loading…
Reference in a new issue