From 64985bb39e5c3c6efa25b4f106e3fe2d5b1c7826 Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Mon, 1 Dec 2025 08:36:29 +0100 Subject: [PATCH] Display application icon --- .../matrix/matrix_event_controller.rs | 2 +- matrixgw_frontend/package-lock.json | 16 ++++++++++++ matrixgw_frontend/package.json | 1 + .../src/widgets/messages/AppIconModifier.tsx | 26 +++++++++++++++++++ .../widgets/messages/MainMessagesWidget.tsx | 9 +++++++ 5 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 matrixgw_frontend/src/widgets/messages/AppIconModifier.tsx diff --git a/matrixgw_backend/src/controllers/matrix/matrix_event_controller.rs b/matrixgw_backend/src/controllers/matrix/matrix_event_controller.rs index da2a1ee..efbe9e0 100644 --- a/matrixgw_backend/src/controllers/matrix/matrix_event_controller.rs +++ b/matrixgw_backend/src/controllers/matrix/matrix_event_controller.rs @@ -216,7 +216,7 @@ pub async fn event_file( MessageType::Video(c) => (c.source(), c.thumbnail_source()), _ => (None, None), }; - + let source = match (query.thumbnail, source, thumb_source) { (false, Some(s), _) => s, (true, _, Some(s)) => s, diff --git a/matrixgw_frontend/package-lock.json b/matrixgw_frontend/package-lock.json index 8da93cc..254aaa2 100644 --- a/matrixgw_frontend/package-lock.json +++ b/matrixgw_frontend/package-lock.json @@ -24,6 +24,7 @@ "qrcode.react": "^4.2.0", "react": "^19.1.1", "react-dom": "^19.1.1", + "react-favicon": "^2.0.7", "react-json-view-lite": "^2.5.0", "react-router": "^7.9.5" }, @@ -3691,6 +3692,21 @@ "react": "^19.2.0" } }, + "node_modules/react-favicon": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/react-favicon/-/react-favicon-2.0.7.tgz", + "integrity": "sha512-Vqjk8VHnOu7vl7JnP13nPJ05DyFGObF655xFkbTUIbF4vqLx1Slbc56Hrbzg1leROAKHzElm3u4KUzaXO46A6A==", + "license": "MIT", + "dependencies": { + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/react-is": { "version": "19.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.0.tgz", diff --git a/matrixgw_frontend/package.json b/matrixgw_frontend/package.json index 7beadb3..fb5008d 100644 --- a/matrixgw_frontend/package.json +++ b/matrixgw_frontend/package.json @@ -26,6 +26,7 @@ "qrcode.react": "^4.2.0", "react": "^19.1.1", "react-dom": "^19.1.1", + "react-favicon": "^2.0.7", "react-json-view-lite": "^2.5.0", "react-router": "^7.9.5" }, diff --git a/matrixgw_frontend/src/widgets/messages/AppIconModifier.tsx b/matrixgw_frontend/src/widgets/messages/AppIconModifier.tsx new file mode 100644 index 0000000..4d10089 --- /dev/null +++ b/matrixgw_frontend/src/widgets/messages/AppIconModifier.tsx @@ -0,0 +1,26 @@ +import Favicon from "react-favicon"; + +// Taken from https://github.com/element-hq/element-web/blob/0577e245dac944bd85eea07b93a9762a93062f62/src/favicon.ts +function getInitialFavicon(): HTMLLinkElement[] { + const icons: HTMLLinkElement[] = []; + const links = window.document + .getElementsByTagName("head")[0] + .getElementsByTagName("link"); + for (const link of links) { + if ( + link.hasAttribute("rel") && + /(^|\s)icon(\s|$)/i.test(link.getAttribute("rel")!) + ) { + icons.push(link); + } + } + return icons; +} + +let iconPath = getInitialFavicon()[0].getAttribute("href")!; + +export function AppIconModifier(p: { + numberUnread: number; +}): React.ReactElement { + return ; +} diff --git a/matrixgw_frontend/src/widgets/messages/MainMessagesWidget.tsx b/matrixgw_frontend/src/widgets/messages/MainMessagesWidget.tsx index f6ac333..8d87f46 100644 --- a/matrixgw_frontend/src/widgets/messages/MainMessagesWidget.tsx +++ b/matrixgw_frontend/src/widgets/messages/MainMessagesWidget.tsx @@ -11,6 +11,7 @@ import type { WsMessage } from "../../api/WsApi"; import { RoomEventsManager } from "../../utils/RoomEventsManager"; import { AsyncWidget } from "../AsyncWidget"; import { useUserInfo } from "../dashboard/BaseAuthenticatedPage"; +import { AppIconModifier } from "./AppIconModifier"; import { MatrixWS } from "./MatrixWS"; import { RoomSelector } from "./RoomSelector"; import { RoomWidget } from "./RoomWidget"; @@ -70,6 +71,11 @@ function _MainMessageWidget(p: { ); }, [space, p.rooms]); + const unreadRooms = React.useMemo( + () => p.rooms.filter((r) => r.number_unread_messages > 0).length, + [p.rooms] + ); + const [_refreshCount, setRefreshCount] = React.useState(0); const [roomMgr, setRoomMgr] = React.useState(); @@ -117,6 +123,9 @@ function _MainMessageWidget(p: { + {/** Application icon modifier */} + + {/* Space selector */}