Add room list avatar option & youtube embed player option

This commit is contained in:
ayes-web 2022-10-08 22:05:00 +03:00
parent 8ea2b0b63b
commit 5c81ba994c
7 changed files with 185 additions and 3 deletions

View file

@ -15,6 +15,7 @@ import ExternalSVG from '../../../../public/res/ic/outlined/external.svg';
import PlaySVG from '../../../../public/res/ic/outlined/play.svg'; import PlaySVG from '../../../../public/res/ic/outlined/play.svg';
import { getBlobSafeMimeType } from '../../../util/mimetypes'; import { getBlobSafeMimeType } from '../../../util/mimetypes';
import initMatrix from '../../../client/initMatrix';
async function getDecryptedBlob(response, type, decryptData) { async function getDecryptedBlob(response, type, decryptData) {
const arrayBuffer = await response.arrayBuffer(); const arrayBuffer = await response.arrayBuffer();
@ -361,6 +362,83 @@ Video.propTypes = {
blurhash: PropTypes.string, blurhash: PropTypes.string,
}; };
export { function YoutubeEmbed({ link }) {
File, Image, Sticker, Audio, Video, 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,
}; };

View file

@ -29,6 +29,7 @@ import IconButton from '../../atoms/button/IconButton';
import Time from '../../atoms/time/Time'; import Time from '../../atoms/time/Time';
import ContextMenu, { MenuHeader, MenuItem, MenuBorder } from '../../atoms/context-menu/ContextMenu'; import ContextMenu, { MenuHeader, MenuItem, MenuBorder } from '../../atoms/context-menu/ContextMenu';
import * as Media from '../media/Media'; import * as Media from '../media/Media';
import settings from '../../../client/state/settings';
import ReplyArrowIC from '../../../../public/res/ic/outlined/reply-arrow.svg'; import ReplyArrowIC from '../../../../public/res/ic/outlined/reply-arrow.svg';
import EmojiAddIC from '../../../../public/res/ic/outlined/emoji-add.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 { confirmDialog } from '../confirm-dialog/ConfirmDialog';
import { getBlobSafeMimeType } from '../../../util/mimetypes'; import { getBlobSafeMimeType } from '../../../util/mimetypes';
import { html, plain } from '../../../util/markdown'; import { html, plain } from '../../../util/markdown';
import { YoutubeEmbed } from '../media/Media';
function PlaceholderMessage() { function PlaceholderMessage() {
return ( return (
@ -716,6 +718,10 @@ function getEditedBody(editedMEvent) {
return [parsedContent.body, isCustomHTML, newContent.formatted_body ?? null]; 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({ function Message({
mEvent, isBodyOnly, roomTimeline, mEvent, isBodyOnly, roomTimeline,
focus, fullTime, isEdit, setEdit, cancelEdit, focus, fullTime, isEdit, setEdit, cancelEdit,
@ -801,6 +807,9 @@ function Message({
isEdited={isEdited} isEdited={isEdited}
/> />
)} )}
{settings.showYoutubeEmbedPlayer && findYoutubeLinks(body).map((link) => (
<YoutubeEmbed key={link} link={link} />
))}
{isEdit && ( {isEdit && (
<MessageEdit <MessageEdit
body={(customHTML body={(customHTML

View file

@ -5,10 +5,12 @@ import './RoomSelector.scss';
import { twemojify } from '../../../util/twemojify'; import { twemojify } from '../../../util/twemojify';
import colorMXID from '../../../util/colorMXID'; import colorMXID from '../../../util/colorMXID';
import initMatrix from '../../../client/initMatrix';
import Text from '../../atoms/text/Text'; import Text from '../../atoms/text/Text';
import Avatar from '../../atoms/avatar/Avatar'; import Avatar from '../../atoms/avatar/Avatar';
import NotificationBadge from '../../atoms/badge/NotificationBadge'; import NotificationBadge from '../../atoms/badge/NotificationBadge';
import { blurOnBubbling } from '../../atoms/button/script'; import { blurOnBubbling } from '../../atoms/button/script';
import settings from '../../../client/state/settings';
function RoomSelectorWrapper({ function RoomSelectorWrapper({
isSelected, isMuted, isUnread, onClick, isSelected, isMuted, isUnread, onClick,
@ -54,6 +56,13 @@ function RoomSelector({
isSelected, isMuted, isUnread, notificationCount, isAlert, isSelected, isMuted, isUnread, notificationCount, isAlert,
options, onClick, onContextMenu, 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 ( return (
<RoomSelectorWrapper <RoomSelectorWrapper
isSelected={isSelected} isSelected={isSelected}
@ -61,6 +70,7 @@ function RoomSelector({
isUnread={isUnread} isUnread={isUnread}
content={( content={(
<> <>
{!settings.showRoomListAvatar && (
<Avatar <Avatar
text={name} text={name}
bgColor={colorMXID(roomId)} bgColor={colorMXID(roomId)}
@ -69,6 +79,15 @@ function RoomSelector({
iconSrc={iconSrc} iconSrc={iconSrc}
size="extra-small" size="extra-small"
/> />
)}
{settings.showRoomListAvatar && (
<Avatar
text={name}
bgColor={colorMXID(roomId)}
imageSrc={avatarSrc}
size="extra-small"
/>
)}
<Text variant="b1" weight={isUnread ? 'medium' : 'normal'}> <Text variant="b1" weight={isUnread ? 'medium' : 'normal'}>
{twemojify(name)} {twemojify(name)}
{parentName && ( {parentName && (

View file

@ -7,7 +7,7 @@ import settings from '../../../client/state/settings';
import navigation from '../../../client/state/navigation'; import navigation from '../../../client/state/navigation';
import { import {
toggleSystemTheme, toggleMarkdown, toggleMembershipEvents, toggleNickAvatarEvents, toggleSystemTheme, toggleMarkdown, toggleMembershipEvents, toggleNickAvatarEvents,
toggleNotifications, toggleNotificationSounds, toggleNotifications, toggleNotificationSounds, toggleShowRoomListAvatar, toggleShowYoutubeEmbedPlayer,
} from '../../../client/action/settings'; } from '../../../client/action/settings';
import { usePermission } from '../../hooks/usePermission'; 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>
<div className="settings-appearance__card"> <div className="settings-appearance__card">
<MenuHeader>Room messages</MenuHeader> <MenuHeader>Room messages</MenuHeader>

View file

@ -42,3 +42,15 @@ export function toggleNotificationSounds() {
type: cons.actions.settings.TOGGLE_NOTIFICATION_SOUNDS, 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,
})
}

View file

@ -72,6 +72,8 @@ const cons = {
TOGGLE_NICKAVATAR_EVENT: 'TOGGLE_NICKAVATAR_EVENT', TOGGLE_NICKAVATAR_EVENT: 'TOGGLE_NICKAVATAR_EVENT',
TOGGLE_NOTIFICATIONS: 'TOGGLE_NOTIFICATIONS', TOGGLE_NOTIFICATIONS: 'TOGGLE_NOTIFICATIONS',
TOGGLE_NOTIFICATION_SOUNDS: 'TOGGLE_NOTIFICATION_SOUNDS', 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: { events: {
@ -144,6 +146,8 @@ const cons = {
NICKAVATAR_EVENTS_TOGGLED: 'NICKAVATAR_EVENTS_TOGGLED', NICKAVATAR_EVENTS_TOGGLED: 'NICKAVATAR_EVENTS_TOGGLED',
NOTIFICATIONS_TOGGLED: 'NOTIFICATIONS_TOGGLED', NOTIFICATIONS_TOGGLED: 'NOTIFICATIONS_TOGGLED',
NOTIFICATION_SOUNDS_TOGGLED: 'NOTIFICATION_SOUNDS_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',
}, },
}, },
}; };

View file

@ -30,6 +30,8 @@ class Settings extends EventEmitter {
this.hideNickAvatarEvents = this.getHideNickAvatarEvents(); this.hideNickAvatarEvents = this.getHideNickAvatarEvents();
this._showNotifications = this.getShowNotifications(); this._showNotifications = this.getShowNotifications();
this.isNotificationSounds = this.getIsNotificationSounds(); this.isNotificationSounds = this.getIsNotificationSounds();
this.showRoomListAvatar = this.getShowRoomListAvatar();
this.showYoutubeEmbedPlayer = this.getShowYoutubeEmbedPlayer();
this.isTouchScreenDevice = ('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0); this.isTouchScreenDevice = ('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0);
} }
@ -147,6 +149,38 @@ class Settings extends EventEmitter {
return settings.isNotificationSounds; 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) { setter(action) {
const actions = { const actions = {
[cons.actions.settings.TOGGLE_SYSTEM_THEME]: () => { [cons.actions.settings.TOGGLE_SYSTEM_THEME]: () => {
@ -186,6 +220,12 @@ class Settings extends EventEmitter {
setSettings('isNotificationSounds', this.isNotificationSounds); setSettings('isNotificationSounds', this.isNotificationSounds);
this.emit(cons.events.settings.NOTIFICATION_SOUNDS_TOGGLED, 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]?.(); actions[action.type]?.();