Merge pull request #1 from ayes-web/url-preview

Url previews
This commit is contained in:
Ayes 2022-11-17 16:53:36 +02:00 committed by GitHub
commit f50e37ea36
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 925 additions and 9759 deletions

View file

@ -16,14 +16,14 @@ jobs:
- name: Setup node - name: Setup node
uses: actions/setup-node@v3.5.1 uses: actions/setup-node@v3.5.1
with: with:
node-version: 17.9.0 node-version: 18.12.1
cache: 'npm' cache: 'npm'
- name: Install dependencies - name: Install dependencies
run: npm ci run: npm ci
- name: Build app - name: Build app
run: npm run build run: npm run build
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v3.1.0 uses: actions/upload-artifact@v3.1.1
with: with:
name: preview name: preview
path: dist path: dist
@ -31,7 +31,7 @@ jobs:
- name: Save pr number - name: Save pr number
run: echo ${PR_NUMBER} > ./pr.txt run: echo ${PR_NUMBER} > ./pr.txt
- name: Upload pr number - name: Upload pr number
uses: actions/upload-artifact@v3.1.0 uses: actions/upload-artifact@v3.1.1
with: with:
name: pr name: pr
path: ./pr.txt path: ./pr.txt

View file

@ -13,16 +13,16 @@ jobs:
if: ${{ github.event.workflow_run.conclusion == 'success' }} if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps: steps:
- name: Download pr number - name: Download pr number
uses: dawidd6/action-download-artifact@46b4ae883bf0726f5949d025d31cb62c7a5ac70c uses: dawidd6/action-download-artifact@e6e25ac3a2b93187502a8be1ef9e9603afc34925
with: with:
workflow: ${{ github.event.workflow.id }} workflow: ${{ github.event.workflow.id }}
run_id: ${{ github.event.workflow_run.id }} run_id: ${{ github.event.workflow_run.id }}
name: pr name: pr
- name: Output pr number - name: Output pr number
id: pr id: pr
run: echo "::set-output name=id::$(<pr.txt)" run: echo "id=$(<pr.txt)" >> $GITHUB_OUTPUT
- name: Download artifact - name: Download artifact
uses: dawidd6/action-download-artifact@46b4ae883bf0726f5949d025d31cb62c7a5ac70c uses: dawidd6/action-download-artifact@e6e25ac3a2b93187502a8be1ef9e9603afc34925
with: with:
workflow: ${{ github.event.workflow.id }} workflow: ${{ github.event.workflow.id }}
run_id: ${{ github.event.workflow_run.id }} run_id: ${{ github.event.workflow_run.id }}

View file

@ -15,7 +15,7 @@ jobs:
- name: Setup node - name: Setup node
uses: actions/setup-node@v3.5.1 uses: actions/setup-node@v3.5.1
with: with:
node-version: 17.9.0 node-version: 18.12.1
cache: 'npm' cache: 'npm'
- name: Install dependencies - name: Install dependencies
run: npm ci run: npm ci

View file

@ -14,7 +14,7 @@ jobs:
- name: Setup node - name: Setup node
uses: actions/setup-node@v3.5.1 uses: actions/setup-node@v3.5.1
with: with:
node-version: 17.9.0 node-version: 18.12.1
cache: 'npm' cache: 'npm'
- name: Install dependencies - name: Install dependencies
run: npm ci run: npm ci
@ -68,7 +68,7 @@ jobs:
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v2.1.0 uses: docker/setup-qemu-action@v2.1.0
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2.1.0 uses: docker/setup-buildx-action@v2.2.1
- name: Login to Docker Hub - name: Login to Docker Hub
uses: docker/login-action@v2.1.0 uses: docker/login-action@v2.1.0
with: with:
@ -82,7 +82,7 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker - name: Extract metadata (tags, labels) for Docker
id: meta id: meta
uses: docker/metadata-action@v4.1.0 uses: docker/metadata-action@v4.1.1
with: with:
images: | images: |
${{ secrets.DOCKER_USERNAME }}/cinny ${{ secrets.DOCKER_USERNAME }}/cinny

View file

@ -1,5 +1,5 @@
## Builder ## Builder
FROM node:17.9.0-alpine3.15 as builder FROM node:18.12.1-alpine3.15 as builder
WORKDIR /src WORKDIR /src
@ -10,7 +10,7 @@ RUN npm run build
## App ## App
FROM nginx:1.23.1-alpine FROM nginx:1.23.2-alpine
COPY --from=builder /src/dist /app COPY --from=builder /src/dist /app

View file

@ -84,7 +84,7 @@ UeGsouhyuITLwEhScounZDqop+Dx
## Local development ## Local development
> We recommend using a version manager as versions change very quickly. You will likely need to switch > We recommend using a version manager as versions change very quickly. You will likely need to switch
between multiple Node.js versions based on the needs of different projects you're working on. [NVM on windows](https://github.com/coreybutler/nvm-windows#installation--upgrades) on Windows and [nvm](https://github.com/nvm-sh/nvm) on Linux/macOS are pretty good choices. Also recommended nodejs version is 16.15.0 LTS. between multiple Node.js versions based on the needs of different projects you're working on. [NVM on windows](https://github.com/coreybutler/nvm-windows#installation--upgrades) on Windows and [nvm](https://github.com/nvm-sh/nvm) on Linux/macOS are pretty good choices. Also recommended nodejs version Hydrogen LTS (v18).
Execute the following commands to start a development server: Execute the following commands to start a development server:
```sh ```sh

View file

@ -1,9 +1,9 @@
{ {
"defaultHomeserver": 3, "defaultHomeserver": 3,
"homeserverList": [ "homeserverList": [
"converser.eu",
"envs.net", "envs.net",
"halogen.city", "halogen.city",
"kde.org",
"matrix.org", "matrix.org",
"mozilla.org" "mozilla.org"
], ],

10418
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -4,8 +4,7 @@
"description": "Yet another matrix client", "description": "Yet another matrix client",
"main": "index.js", "main": "index.js",
"engines": { "engines": {
"npm": ">=6.14.8", "node": ">=16.0.0"
"node": ">=14.15.0"
}, },
"scripts": { "scripts": {
"start": "webpack serve --config ./webpack.dev.js --open", "start": "webpack serve --config ./webpack.dev.js --open",
@ -15,13 +14,13 @@
"author": "Ajay Bura", "author": "Ajay Bura",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@fontsource/inter": "4.5.13", "@fontsource/inter": "4.5.14",
"@fontsource/roboto": "4.5.8", "@fontsource/roboto": "4.5.8",
"@khanacademy/simple-markdown": "0.8.5", "@khanacademy/simple-markdown": "0.8.5",
"@matrix-org/olm": "3.2.13", "@matrix-org/olm": "3.2.13",
"@tippyjs/react": "4.2.6", "@tippyjs/react": "4.2.6",
"babel-polyfill": "6.26.0", "babel-polyfill": "6.26.0",
"blurhash": "2.0.3", "blurhash": "2.0.4",
"browser-encrypt-attachment": "0.3.0", "browser-encrypt-attachment": "0.3.0",
"dateformat": "5.0.3", "dateformat": "5.0.3",
"emojibase-data": "7.0.1", "emojibase-data": "7.0.1",
@ -29,37 +28,37 @@
"flux": "4.0.3", "flux": "4.0.3",
"formik": "2.2.9", "formik": "2.2.9",
"html-react-parser": "3.0.4", "html-react-parser": "3.0.4",
"katex": "0.16.2", "katex": "0.16.3",
"linkify-html": "4.0.2", "linkify-html": "4.0.2",
"linkifyjs": "4.0.2", "linkifyjs": "4.0.2",
"matrix-js-sdk": "20.0.2", "matrix-js-sdk": "21.1.0",
"prop-types": "15.8.1", "prop-types": "15.8.1",
"react": "17.0.2", "react": "17.0.2",
"react-autosize-textarea": "7.1.0", "react-autosize-textarea": "7.1.0",
"react-blurhash": "0.1.3", "react-blurhash": "0.2.0",
"react-dnd": "15.1.2", "react-dnd": "15.1.2",
"react-dnd-html5-backend": "15.1.3", "react-dnd-html5-backend": "15.1.3",
"react-dom": "17.0.2", "react-dom": "17.0.2",
"react-google-recaptcha": "2.1.0", "react-google-recaptcha": "2.1.0",
"react-modal": "3.15.1", "react-modal": "3.16.1",
"sanitize-html": "2.7.2", "sanitize-html": "2.7.3",
"tippy.js": "6.3.7", "tippy.js": "6.3.7",
"twemoji": "14.0.2" "twemoji": "14.0.2"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "7.19.3", "@babel/core": "7.20.2",
"@babel/preset-env": "7.19.4", "@babel/preset-env": "7.20.2",
"@babel/preset-react": "7.18.6", "@babel/preset-react": "7.18.6",
"assert": "2.0.0", "assert": "2.0.0",
"babel-loader": "8.2.5", "babel-loader": "8.3.0",
"browserify-fs": "1.0.0", "browserify-fs": "1.0.0",
"buffer": "6.0.3", "buffer": "6.0.3",
"clean-webpack-plugin": "4.0.0", "clean-webpack-plugin": "4.0.0",
"copy-webpack-plugin": "11.0.0", "copy-webpack-plugin": "11.0.0",
"crypto-browserify": "3.12.0", "crypto-browserify": "3.12.0",
"css-loader": "6.7.1", "css-loader": "6.7.2",
"css-minimizer-webpack-plugin": "4.1.0", "css-minimizer-webpack-plugin": "4.2.2",
"eslint": "8.25.0", "eslint": "8.27.0",
"eslint-config-airbnb": "19.0.4", "eslint-config-airbnb": "19.0.4",
"eslint-plugin-import": "2.26.0", "eslint-plugin-import": "2.26.0",
"eslint-plugin-jsx-a11y": "6.6.1", "eslint-plugin-jsx-a11y": "6.6.1",
@ -69,13 +68,13 @@
"html-webpack-plugin": "5.5.0", "html-webpack-plugin": "5.5.0",
"mini-css-extract-plugin": "2.6.1", "mini-css-extract-plugin": "2.6.1",
"path-browserify": "1.0.1", "path-browserify": "1.0.1",
"sass": "1.55.0", "sass": "1.56.1",
"sass-loader": "13.1.0", "sass-loader": "13.2.0",
"stream-browserify": "3.0.0", "stream-browserify": "3.0.0",
"style-loader": "3.3.1", "style-loader": "3.3.1",
"url": "0.11.0", "url": "0.11.0",
"util": "0.12.4", "util": "0.12.5",
"webpack": "5.74.0", "webpack": "5.75.0",
"webpack-cli": "4.10.0", "webpack-cli": "4.10.0",
"webpack-dev-server": "4.11.1", "webpack-dev-server": "4.11.1",
"webpack-merge": "5.8.0" "webpack-merge": "5.8.0"

View file

@ -27,9 +27,7 @@ function ImagePackUpload({ onUpload }) {
setProgress(true); setProgress(true);
const image = await scaleDownImage(imgFile, 512, 512); const image = await scaleDownImage(imgFile, 512, 512);
const url = await mx.uploadContent(image, { const { content_uri: url } = await mx.uploadContent(image);
onlyContentUri: true,
});
onUpload(shortcode, url); onUpload(shortcode, url);
setProgress(false); setProgress(false);

View file

@ -22,7 +22,7 @@ function ImageUpload({
const file = e.target.files.item(0); const file = e.target.files.item(0);
if (file === null) return; if (file === null) return;
try { try {
const uPromise = initMatrix.matrixClient.uploadContent(file, { onlyContentUri: false }); const uPromise = initMatrix.matrixClient.uploadContent(file);
setUploadPromise(uPromise); setUploadPromise(uPromise);
const res = await uPromise; const res = await uPromise;

View file

@ -416,31 +416,76 @@ function Embed({ link }) {
return <YoutubeEmbed link={link} />; return <YoutubeEmbed link={link} />;
} }
// TODO: url preview const [urlPreviewInfo, setUrlPreviewInfo] = useState();
// const [urlPreviewInfo, setUrlPreviewInfo] = useState(null); const mx = initMatrix.matrixClient;
// const mx = initMatrix.matrixClient;
// useEffect(() => { useEffect(() => {
// let unmounted = false; let unmounted = false;
// async function getThumbnail() { async function getUrlPreview() {
// const info = await mx.getUrlPreview(link, 0); try {
// console.log('DEBUG', info); const info = await mx.getUrlPreview(link, 0);
// if (unmounted) return; if (unmounted) return;
setUrlPreviewInfo(info);
} catch {
setUrlPreviewInfo();
}
}
// setUrlPreviewInfo(info); getUrlPreview();
// }
// getThumbnail(); return () => {
unmounted = true;
};
});
// return () => { if (urlPreviewInfo != null) {
// unmounted = true; const imageURL = urlPreviewInfo['og:image'] || urlPreviewInfo['og:image:secure_url'];
// }; const image = (imageURL != null) ? (
// }); <Image
link={mx.mxcUrlToHttp(imageURL)}
height={urlPreviewInfo['og:image:height'] != null ? parseInt(urlPreviewInfo['og:image:height'], 10) : null}
width={urlPreviewInfo['og:image:width'] != null ? parseInt(urlPreviewInfo['og:image:width'], 10) : null}
name={urlPreviewInfo['og:image:alt'] || urlPreviewInfo['og:site_name'] || ''}
type={urlPreviewInfo['og:image:type'] != null ? urlPreviewInfo['og:image:type'] : null}
/>
) : null;
// if (urlPreviewInfo !== null) { // Image only embed
// return <div>url preview here!/div>; if (image != null && urlPreviewInfo['og:title'] == null && urlPreviewInfo['og:description'] == null) {
// } return (
<div className="file-container">
{image}
</div>
);
}
const embedTitle = urlPreviewInfo['og:title'] || urlPreviewInfo['og:site_name'];
return (
<div className="file-container">
<div className="embed-container">
<div className="embed-text">
{(embedTitle != null) && (
<Text className="embed-title" variant="h2">
{embedTitle}
</Text>
)}
{(urlPreviewInfo['og:description'] != null) && (
<Text className="embed-description" variant="b3">
{urlPreviewInfo['og:description']}
</Text>
)}
</div>
<div className="embed-media">
{image}
</div>
</div>
</div>
);
}
return null; return null;
} }

View file

@ -88,3 +88,14 @@
width: 100%; width: 100%;
} }
} }
.embed-container {
color: var(--tc-surface-low);
background-color: var(--bg-surface-hover);
border-radius: calc(var(--bo-radius) / 2);
padding: 15px;
.embed-text {
margin-bottom: 5px;
}
}

View file

@ -43,6 +43,7 @@ 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 { Embed } from '../media/Media'; import { Embed } from '../media/Media';
import settings from '../../../client/state/settings';
function PlaceholderMessage() { function PlaceholderMessage() {
return ( return (
@ -808,7 +809,7 @@ function Message({
isEdited={isEdited} isEdited={isEdited}
/> />
)} )}
{msgType === 'm.text' && findLinks(body).map((link) => ( {settings.showUrlPreview && msgType === 'm.text' && findLinks(body).map((link) => (
<Embed key={link.href} link={link.href} /> <Embed key={link.href} link={link.href} />
))} ))}
{isEdit && ( {isEdit && (

View file

@ -70,7 +70,14 @@ function RoomSelector({
isUnread={isUnread} isUnread={isUnread}
content={( content={(
<> <>
{!settings.showRoomListAvatar && ( {settings.showRoomListAvatar ? (
<Avatar
text={name}
bgColor={colorMXID(roomId)}
imageSrc={avatarSrc}
size="extra-small"
/>
) : (
<Avatar <Avatar
text={name} text={name}
bgColor={colorMXID(roomId)} bgColor={colorMXID(roomId)}
@ -80,14 +87,6 @@ function RoomSelector({
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,8 @@ 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, toggleShowRoomListAvatar, toggleShowYoutubeEmbedPlayer, toggleNotifications, toggleNotificationSounds, toggleShowRoomListAvatar,
toggleShowYoutubeEmbedPlayer, toggleShowUrlPreview,
} from '../../../client/action/settings'; } from '../../../client/action/settings';
import { usePermission } from '../../hooks/usePermission'; import { usePermission } from '../../hooks/usePermission';
@ -90,12 +91,26 @@ function AppearanceSection() {
)} )}
content={<Text variant="b3">Will show room avatars in the room list.</Text>} content={<Text variant="b3">Will show room avatars in the room list.</Text>}
/> />
</div>
<div className="settings-appearance__card">
<MenuHeader>URL Previews</MenuHeader>
<SettingTile
title="Show URL previews"
options={(
<Toggle
isActive={settings.showUrlPreview}
onToggle={() => { toggleShowUrlPreview(); updateState({}); }}
/>
)}
content={<Text variant="b3">Show additional info about urls.</Text>}
/>
<SettingTile <SettingTile
title="Show Youtube embed player" title="Show Youtube embed player"
options={( options={(
<Toggle <Toggle
isActive={settings.showYoutubeEmbedPlayer} isActive={settings.showYoutubeEmbedPlayer}
onToggle={() => { toggleShowYoutubeEmbedPlayer(); updateState({}); }} onToggle={() => { toggleShowYoutubeEmbedPlayer(); updateState({}); }}
disabled={!settings.showUrlPreview}
/> />
)} )}
content={<Text variant="b3">Will show a youtube embed player for youtube links.</Text>} content={<Text variant="b3">Will show a youtube embed player for youtube links.</Text>}

View file

@ -236,16 +236,12 @@ async function createRoom(opts) {
}); });
} }
if (parentId && joinRule === 'restricted') { if (parentId && joinRule === 'restricted') {
try {
const caps = await mx.getCapabilities(); const caps = await mx.getCapabilities();
options.room_version = caps if (caps['m.room_versions'].available?.['9'] !== 'stable') {
?.['m.room_versions'] throw new Error("ERROR: The server doesn't support restricted rooms");
?.['org.matrix.msc3244.room_capabilities'] }
?.restricted if (Number(caps['m.room_versions'].default) < 9) {
?.preferred options.room_version = '9';
|| undefined;
} catch {
console.error('Can\'t find room version for restricted.');
} }
options.initial_state.push({ options.initial_state.push({
type: 'm.room.join_rules', type: 'm.room.join_rules',

View file

@ -54,3 +54,9 @@ export function toggleShowYoutubeEmbedPlayer() {
type: cons.actions.settings.TOGGLE_SHOW_YOUTUBE_EMBED_PLAYER, type: cons.actions.settings.TOGGLE_SHOW_YOUTUBE_EMBED_PLAYER,
}); });
} }
export function toggleShowUrlPreview() {
appDispatcher.dispatch({
type: cons.actions.settings.TOGGLE_SHOW_URL_PREVIEW,
});
}

View file

@ -395,7 +395,7 @@ class RoomsInput extends EventEmitter {
input.attachment.uploadingPromise = uploadingPromise; input.attachment.uploadingPromise = uploadingPromise;
this.roomIdToInput.set(roomId, input); this.roomIdToInput.set(roomId, input);
const url = await uploadingPromise; const { content_uri: url } = await uploadingPromise;
delete input.attachment.uploadingPromise; delete input.attachment.uploadingPromise;
this.roomIdToInput.set(roomId, input); this.roomIdToInput.set(roomId, input);

View file

@ -74,6 +74,7 @@ const cons = {
TOGGLE_NOTIFICATION_SOUNDS: 'TOGGLE_NOTIFICATION_SOUNDS', TOGGLE_NOTIFICATION_SOUNDS: 'TOGGLE_NOTIFICATION_SOUNDS',
TOGGLE_SHOW_ROOM_LIST_AVATAR: 'TOGGLE_SHOW_ROOM_LIST_AVATAR', TOGGLE_SHOW_ROOM_LIST_AVATAR: 'TOGGLE_SHOW_ROOM_LIST_AVATAR',
TOGGLE_SHOW_YOUTUBE_EMBED_PLAYER: 'TOGGLE_SHOW_YOUTUBE_EMBED_PLAYER', TOGGLE_SHOW_YOUTUBE_EMBED_PLAYER: 'TOGGLE_SHOW_YOUTUBE_EMBED_PLAYER',
TOGGLE_SHOW_URL_PREVIEW: 'TOGGLE_SHOW_URL_PREVIEW',
}, },
}, },
events: { events: {
@ -148,6 +149,7 @@ const cons = {
NOTIFICATION_SOUNDS_TOGGLED: 'NOTIFICATION_SOUNDS_TOGGLED', NOTIFICATION_SOUNDS_TOGGLED: 'NOTIFICATION_SOUNDS_TOGGLED',
SHOW_ROOM_LIST_AVATAR_TOGGLED: 'SHOW_ROOM_LIST_AVATAR_TOGGLED', SHOW_ROOM_LIST_AVATAR_TOGGLED: 'SHOW_ROOM_LIST_AVATAR_TOGGLED',
SHOW_YOUTUBE_EMBED_PLAYER_TOGGLED: 'SHOW_YOUTUBE_EMBED_PLAYER_TOGGLED', SHOW_YOUTUBE_EMBED_PLAYER_TOGGLED: 'SHOW_YOUTUBE_EMBED_PLAYER_TOGGLED',
TOGGLE_SHOW_URL_PREVIEW: 'TOGGLE_SHOW_URL_PREVIEW',
}, },
}, },
}; };

View file

@ -32,6 +32,7 @@ class Settings extends EventEmitter {
this.isNotificationSounds = this.getIsNotificationSounds(); this.isNotificationSounds = this.getIsNotificationSounds();
this.showRoomListAvatar = this.getShowRoomListAvatar(); this.showRoomListAvatar = this.getShowRoomListAvatar();
this.showYoutubeEmbedPlayer = this.getShowYoutubeEmbedPlayer(); this.showYoutubeEmbedPlayer = this.getShowYoutubeEmbedPlayer();
this.showUrlPreview = this.getShowUrlPreview();
this.isTouchScreenDevice = ('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0); this.isTouchScreenDevice = ('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0);
} }
@ -181,6 +182,22 @@ class Settings extends EventEmitter {
return settings.showYoutubeEmbedPlayer; return settings.showYoutubeEmbedPlayer;
} }
toggleShowUrlPreview() {
this.showUrlPreview = !this.showUrlPreview;
setSettings('showUrlPreview', this.showUrlPreview);
this.emit(cons.events.settings.SHOW_URL_PREVIEW_TOGGLED, this.showUrlPreview);
}
getShowUrlPreview() {
if (typeof this.showUrlPreview === 'boolean') return this.showUrlPreview;
const settings = getSettings();
if (settings === null) return false;
if (typeof settings.showUrlPreview === 'undefined') return false;
return settings.showUrlPreview;
}
setter(action) { setter(action) {
const actions = { const actions = {
[cons.actions.settings.TOGGLE_SYSTEM_THEME]: () => { [cons.actions.settings.TOGGLE_SYSTEM_THEME]: () => {
@ -226,6 +243,9 @@ class Settings extends EventEmitter {
[cons.actions.settings.TOGGLE_SHOW_YOUTUBE_EMBED_PLAYER]: () => { [cons.actions.settings.TOGGLE_SHOW_YOUTUBE_EMBED_PLAYER]: () => {
this.toggleShowYoutubeEmbedPlayer(); this.toggleShowYoutubeEmbedPlayer();
}, },
[cons.actions.settings.TOGGLE_SHOW_URL_PREVIEW]: () => {
this.toggleShowUrlPreview();
},
}; };
actions[action.type]?.(); actions[action.type]?.();