From 116043828db9f0834d32309d95199068f338fca9 Mon Sep 17 00:00:00 2001 From: Jean Brito Date: Fri, 15 Dec 2023 12:52:58 -0300 Subject: [PATCH 1/9] new window --- src/documentViewer/ipc.ts | 25 +++++++++++++++++++++++++ src/ipc/channels.ts | 5 +++++ src/main.ts | 2 ++ src/servers/preload/api.ts | 3 +++ src/servers/preload/documentViewer.ts | 10 ++++++++++ src/ui/main/serverView/index.ts | 1 - 6 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 src/documentViewer/ipc.ts create mode 100644 src/servers/preload/documentViewer.ts diff --git a/src/documentViewer/ipc.ts b/src/documentViewer/ipc.ts new file mode 100644 index 000000000..ace010e62 --- /dev/null +++ b/src/documentViewer/ipc.ts @@ -0,0 +1,25 @@ +import { BrowserWindow } from 'electron'; + +import { handle } from '../ipc/main'; + +export const startDocumentViewerHandler = (): void => { + handle('document-viewer/open-window', async (event, url, format, options) => { + const validUrl = new URL(url); + const allowedProtocols = ['http:', 'https:']; + if (!allowedProtocols.includes(validUrl.protocol)) { + return; + } + const documentViewerWindow = new BrowserWindow({ + width: 800, + height: 600, + webPreferences: { + session: event.session, + plugins: true, + }, + }); + documentViewerWindow.loadURL(url); + documentViewerWindow.on('ready-to-show', () => { + documentViewerWindow.show(); + }); + }); +}; diff --git a/src/ipc/channels.ts b/src/ipc/channels.ts index 0c978177e..13a4017be 100644 --- a/src/ipc/channels.ts +++ b/src/ipc/channels.ts @@ -41,6 +41,11 @@ type ChannelToArgsMap = { 'outlook-calendar/has-credentials': () => Promise; 'outlook-calendar/clear-credentials': () => void; 'outlook-calendar/set-user-token': (token: string, userId: string) => void; + 'document-viewer/open-window': ( + url: string, + format: string, + options: any + ) => void; }; export type Channel = keyof ChannelToArgsMap; diff --git a/src/main.ts b/src/main.ts index 1c73801e5..8bb26c6d0 100644 --- a/src/main.ts +++ b/src/main.ts @@ -8,6 +8,7 @@ import { } from './app/main/data'; import { setUserDataDirectory } from './app/main/dev'; import { setupDeepLinks, processDeepLinksInArgs } from './deepLinks/main'; +import { startDocumentViewerHandler } from './documentViewer/ipc'; import { setupDownloads } from './downloads/main'; import { setupMainErrorHandling } from './errors'; import i18n from './i18n/main'; @@ -98,6 +99,7 @@ const start = async (): Promise => { handleJitsiDesktopCapturerGetSources(); handleDesktopCapturerGetSources(); startOutlookCalendarUrlHandler(); + startDocumentViewerHandler(); checkSupportedVersionServers(); await processDeepLinksInArgs(); diff --git a/src/servers/preload/api.ts b/src/servers/preload/api.ts index cabf221dc..40c6ee33d 100644 --- a/src/servers/preload/api.ts +++ b/src/servers/preload/api.ts @@ -14,6 +14,7 @@ import { setUserPresenceDetection } from '../../userPresence/preload'; import type { Server } from '../common'; import { setBadge } from './badge'; import { writeTextToClipboard } from './clipboard'; +import { openDocumentViewer } from './documentViewer'; import { setFavicon } from './favicon'; import { setGitCommitHash } from './gitCommitHash'; import type { videoCallWindowOptions } from './internalVideoChatWindow'; @@ -72,6 +73,7 @@ export type RocketChatDesktopAPI = { hasOutlookCredentials: () => Promise; clearOutlookCredentials: () => void; setUserToken: (token: string, userId: string) => void; + openDocumentViewer: (url: string, format: string, options: any) => void; }; export const RocketChatDesktop: RocketChatDesktopAPI = { @@ -105,4 +107,5 @@ export const RocketChatDesktop: RocketChatDesktopAPI = { clearOutlookCredentials, setUserToken, setSidebarCustomTheme, + openDocumentViewer, }; diff --git a/src/servers/preload/documentViewer.ts b/src/servers/preload/documentViewer.ts new file mode 100644 index 000000000..37dc20cc0 --- /dev/null +++ b/src/servers/preload/documentViewer.ts @@ -0,0 +1,10 @@ +import { ipcRenderer } from 'electron'; + +export const openDocumentViewer = ( + url: string, + format: string, + options: any +): void => { + console.log('document-viewer/open-window', url, format, options); + ipcRenderer.invoke('document-viewer/open-window', url, format, options); +}; diff --git a/src/ui/main/serverView/index.ts b/src/ui/main/serverView/index.ts index 1c9cbc7f3..868f38d84 100644 --- a/src/ui/main/serverView/index.ts +++ b/src/ui/main/serverView/index.ts @@ -325,7 +325,6 @@ export const attachGuestWebContentsEvents = async (): Promise => { guestWebContents.session.on( 'will-download', (event, item, _webContents) => { - console.log('will-download', item); const fileName = item.getFilename(); const extension = path.extname(fileName)?.slice(1).toLowerCase(); const savePath = dialog.showSaveDialogSync(rootWindow, { From 7964add70b402ef32cc3fcf70ba2a924e0f1d69a Mon Sep 17 00:00:00 2001 From: Jean Brito Date: Mon, 18 Dec 2023 17:16:53 -0300 Subject: [PATCH 2/9] open PDF viewer above the chat webview --- src/documentViewer/ipc.ts | 44 +++++++------ src/servers/actions.ts | 6 ++ src/servers/common.ts | 1 + src/servers/preload/documentViewer.ts | 1 - src/servers/reducers.ts | 10 ++- .../components/ServersView/DocumentViewer.tsx | 62 +++++++++++++++++++ src/ui/components/ServersView/ServerPane.tsx | 36 ++++++++++- src/ui/components/ServersView/index.tsx | 1 + 8 files changed, 137 insertions(+), 24 deletions(-) create mode 100644 src/ui/components/ServersView/DocumentViewer.tsx diff --git a/src/documentViewer/ipc.ts b/src/documentViewer/ipc.ts index ace010e62..07b049b74 100644 --- a/src/documentViewer/ipc.ts +++ b/src/documentViewer/ipc.ts @@ -1,25 +1,29 @@ -import { BrowserWindow } from 'electron'; - import { handle } from '../ipc/main'; +import { SERVER_DOCUMENT_VIEWER_OPEN_URL } from '../servers/actions'; +import { dispatch, select } from '../store'; export const startDocumentViewerHandler = (): void => { - handle('document-viewer/open-window', async (event, url, format, options) => { - const validUrl = new URL(url); - const allowedProtocols = ['http:', 'https:']; - if (!allowedProtocols.includes(validUrl.protocol)) { - return; + handle( + 'document-viewer/open-window', + async (event, url, _format, _options) => { + const validUrl = new URL(url); + const allowedProtocols = ['http:', 'https:']; + if (!allowedProtocols.includes(validUrl.protocol)) { + return; + } + const server = select(({ servers }) => + servers.find( + (s) => new URL(s.url).origin === new URL(event.getURL()).origin + ) + ); + if (!server) { + return; + } + + dispatch({ + type: SERVER_DOCUMENT_VIEWER_OPEN_URL, + payload: { server: server.url, documentUrl: url }, + }); } - const documentViewerWindow = new BrowserWindow({ - width: 800, - height: 600, - webPreferences: { - session: event.session, - plugins: true, - }, - }); - documentViewerWindow.loadURL(url); - documentViewerWindow.on('ready-to-show', () => { - documentViewerWindow.show(); - }); - }); + ); }; diff --git a/src/servers/actions.ts b/src/servers/actions.ts index bbf75e165..feb497760 100644 --- a/src/servers/actions.ts +++ b/src/servers/actions.ts @@ -4,6 +4,8 @@ export const SERVERS_LOADED = 'servers/loaded'; export const SERVER_URL_RESOLUTION_REQUESTED = 'server/url-resolution-requested'; export const SERVER_URL_RESOLVED = 'server/url-resolved'; +export const SERVER_DOCUMENT_VIEWER_OPEN_URL = + 'server/document-viewer/open-url'; export type ServersActionTypeToPayloadMap = { [SERVERS_LOADED]: { @@ -12,4 +14,8 @@ export type ServersActionTypeToPayloadMap = { }; [SERVER_URL_RESOLUTION_REQUESTED]: Server['url']; [SERVER_URL_RESOLVED]: ServerUrlResolutionResult; + [SERVER_DOCUMENT_VIEWER_OPEN_URL]: { + server: Server['url']; + documentUrl: string; + }; }; diff --git a/src/servers/common.ts b/src/servers/common.ts index 0945f9f11..3c7ee1796 100644 --- a/src/servers/common.ts +++ b/src/servers/common.ts @@ -25,6 +25,7 @@ export type Server = { supportedVersionsSource?: 'server' | 'cloud' | 'builtin'; supportedVersions?: SupportedVersions; expirationMessageLastTimeShown?: Date; + documentViewerOpenUrl?: string; }; export const enum ServerUrlResolutionStatus { diff --git a/src/servers/preload/documentViewer.ts b/src/servers/preload/documentViewer.ts index 37dc20cc0..1f43464bb 100644 --- a/src/servers/preload/documentViewer.ts +++ b/src/servers/preload/documentViewer.ts @@ -5,6 +5,5 @@ export const openDocumentViewer = ( format: string, options: any ): void => { - console.log('document-viewer/open-window', url, format, options); ipcRenderer.invoke('document-viewer/open-window', url, format, options); }; diff --git a/src/servers/reducers.ts b/src/servers/reducers.ts index d59fca719..69238a3cb 100644 --- a/src/servers/reducers.ts +++ b/src/servers/reducers.ts @@ -28,7 +28,7 @@ import { WEBVIEW_SIDEBAR_CUSTOM_THEME_CHANGED, WEBVIEW_SERVER_SUPPORTED_VERSIONS_SOURCE_UPDATED, } from '../ui/actions'; -import { SERVERS_LOADED } from './actions'; +import { SERVERS_LOADED, SERVER_DOCUMENT_VIEWER_OPEN_URL } from './actions'; import type { Server } from './common'; const ensureUrlFormat = (serverUrl: string | null): string => { @@ -65,7 +65,8 @@ type ServersActionTypes = | ActionOf | ActionOf | ActionOf - | ActionOf; + | ActionOf + | ActionOf; const upsert = (state: Server[], server: Server): Server[] => { const index = state.findIndex(({ url }) => url === server.url); @@ -238,6 +239,11 @@ export const servers: Reducer = ( return upsert(state, { url, outlookCredentials }); } + case SERVER_DOCUMENT_VIEWER_OPEN_URL: { + const { server, documentUrl } = action.payload; + return upsert(state, { url: server, documentViewerOpenUrl: documentUrl }); + } + default: return state; } diff --git a/src/ui/components/ServersView/DocumentViewer.tsx b/src/ui/components/ServersView/DocumentViewer.tsx new file mode 100644 index 000000000..e776cfb06 --- /dev/null +++ b/src/ui/components/ServersView/DocumentViewer.tsx @@ -0,0 +1,62 @@ +import { Box, IconButton } from '@rocket.chat/fuselage'; +import React, { useState, useEffect } from 'react'; + +const DynamicWebview = ({ + url, + isActive, + partition, + closeDocumentViewer, +}: { + url: string; + isActive: boolean; + partition: string; + closeDocumentViewer: () => void; +}) => { + const [webView, setWebView] = useState(null); + + useEffect(() => { + if (isActive && url) { + setWebView( + + ); + } else { + setWebView(null); + } + }, [url, isActive, partition]); + + return ( + <> + {isActive && ( + + + +

PDF Viewer

+
+ +
{webView}
+
+ )} + + ); +}; + +export default DynamicWebview; diff --git a/src/ui/components/ServersView/ServerPane.tsx b/src/ui/components/ServersView/ServerPane.tsx index a74dd05f7..4228c5c82 100644 --- a/src/ui/components/ServersView/ServerPane.tsx +++ b/src/ui/components/ServersView/ServerPane.tsx @@ -1,14 +1,16 @@ import type { FC } from 'react'; -import React, { useRef, useEffect } from 'react'; +import React, { useRef, useEffect, useState } from 'react'; import { useDispatch } from 'react-redux'; import type { Dispatch } from 'redux'; +import { SERVER_DOCUMENT_VIEWER_OPEN_URL } from '../../../servers/actions'; import type { RootAction } from '../../../store/actions'; import { LOADING_ERROR_VIEW_RELOAD_SERVER_CLICKED, WEBVIEW_ATTACHED, WEBVIEW_READY, } from '../../actions'; +import DocumentViewer from './DocumentViewer'; import ErrorView from './ErrorView'; import UnsupportedServer from './UnsupportedServer'; import { StyledWebView, Wrapper } from './styles'; @@ -20,6 +22,7 @@ type ServerPaneProps = { isFailed: boolean; isSupported: boolean | undefined; title: string | undefined; + documentViewerOpenUrl: string | undefined; }; export const ServerPane: FC = ({ @@ -28,9 +31,12 @@ export const ServerPane: FC = ({ isSelected, isFailed, isSupported, + documentViewerOpenUrl, }) => { const dispatch = useDispatch>(); + const [documentViewerActive, setDocumentViewerActive] = useState(false); + const webviewRef = useRef>(null); @@ -137,6 +143,19 @@ export const ServerPane: FC = ({ } }, [lastPath, serverUrl]); + useEffect(() => { + const webview = webviewRef.current; + if (!webview) { + return; + } + + if (isSelected && documentViewerOpenUrl && documentViewerOpenUrl !== '') { + setDocumentViewerActive(true); + } else { + setDocumentViewerActive(false); + } + }, [documentViewerOpenUrl, isSelected]); + const handleReload = (): void => { dispatch({ type: LOADING_ERROR_VIEW_RELOAD_SERVER_CLICKED, @@ -153,8 +172,17 @@ export const ServerPane: FC = ({ } else { webview?.blur(); } + // setdocumentViewerActive(true); }, [isSelected]); + const closeDocumentViewer = () => { + dispatch({ + type: SERVER_DOCUMENT_VIEWER_OPEN_URL, + payload: { server: serverUrl, documentUrl: '' }, + }); + setDocumentViewerActive(false); + }; + return ( = ({ partition={`persist:${serverUrl}`} {...({ allowpopups: 'allowpopups' } as any)} />{' '} + { isFailed={server.failed ?? false} isSupported={server.isSupportedVersion} title={server.title} + documentViewerOpenUrl={server.documentViewerOpenUrl} /> ))} From 3eb45e45632e74dcfa4f1650b76e01b9786b9f62 Mon Sep 17 00:00:00 2001 From: Jean Brito Date: Wed, 20 Dec 2023 16:07:08 -0300 Subject: [PATCH 3/9] fix upper bar --- src/ui/components/ServersView/DocumentViewer.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ui/components/ServersView/DocumentViewer.tsx b/src/ui/components/ServersView/DocumentViewer.tsx index e776cfb06..beb7d9412 100644 --- a/src/ui/components/ServersView/DocumentViewer.tsx +++ b/src/ui/components/ServersView/DocumentViewer.tsx @@ -24,7 +24,7 @@ const DynamicWebview = ({ height: '100%', position: 'absolute', left: 0, - top: 64, + top: 50, right: 0, bottom: 0, }} @@ -47,12 +47,12 @@ const DynamicWebview = ({ content='center' alignItems='center' > - +

PDF Viewer

-
{webView}
+ {webView}
)} From 6f5c56710e076c689550010d4e600c6e24b0865d Mon Sep 17 00:00:00 2001 From: gabriellsh Date: Fri, 22 Dec 2023 16:42:17 -0300 Subject: [PATCH 4/9] Add margin --- src/ui/components/ServersView/DocumentViewer.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ui/components/ServersView/DocumentViewer.tsx b/src/ui/components/ServersView/DocumentViewer.tsx index beb7d9412..7dac506a5 100644 --- a/src/ui/components/ServersView/DocumentViewer.tsx +++ b/src/ui/components/ServersView/DocumentViewer.tsx @@ -48,7 +48,11 @@ const DynamicWebview = ({ alignItems='center' > - +

PDF Viewer

From 6a91dd06e62b7246daef74cad9c5f0fce32f8dd6 Mon Sep 17 00:00:00 2001 From: Jean Brito Date: Tue, 26 Dec 2023 15:48:15 -0300 Subject: [PATCH 5/9] expose RocketChatDesktop earlier --- src/preload.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/preload.ts b/src/preload.ts index d562a3d7b..46e88c78b 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -24,6 +24,7 @@ declare global { } contextBridge.exposeInMainWorld('JitsiMeetElectron', JitsiMeetElectron); +contextBridge.exposeInMainWorld('RocketChatDesktop', RocketChatDesktop); const start = async (): Promise => { console.log('[Rocket.Chat Desktop] preload.ts start'); @@ -36,8 +37,6 @@ const start = async (): Promise => { window.removeEventListener('load', start); - contextBridge.exposeInMainWorld('RocketChatDesktop', RocketChatDesktop); - setServerUrl(serverUrl); await whenReady(); From 69bedd3592655b9fc1213f7b09e536226fcade1d Mon Sep 17 00:00:00 2001 From: Tasso Evangelista Date: Mon, 15 Jan 2024 13:10:45 -0300 Subject: [PATCH 6/9] Fix memory leak --- src/ui/main/rootWindow.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/main/rootWindow.ts b/src/ui/main/rootWindow.ts index 0e4225f92..11ad6a4ed 100644 --- a/src/ui/main/rootWindow.ts +++ b/src/ui/main/rootWindow.ts @@ -394,7 +394,7 @@ export const showRootWindow = async (): Promise => { } return new Promise((resolve) => { - browserWindow.addListener('ready-to-show', () => { + browserWindow.once('ready-to-show', () => { applyRootWindowState(browserWindow); const isTrayIconEnabled = select( @@ -422,7 +422,7 @@ export const exportLocalStorage = async (): Promise> => { tempWindow.loadFile(path.join(app.getAppPath(), 'app/index.html')); await new Promise((resolve) => { - tempWindow.addListener('ready-to-show', () => { + tempWindow.once('ready-to-show', () => { resolve(); }); }); From ff7e060f807ffa258425a0724218d2088f56b494 Mon Sep 17 00:00:00 2001 From: Jean Brito Date: Tue, 6 Feb 2024 14:02:38 -0300 Subject: [PATCH 7/9] fix bug when the app is quit with a pdf opened --- .nvmrc | 1 - src/servers/reducers.ts | 24 +++--- .../components/ServersView/DocumentViewer.tsx | 77 +++++++------------ src/ui/components/ServersView/ServerPane.tsx | 71 ++++++++--------- src/ui/components/ServersView/styles.tsx | 10 +++ 5 files changed, 87 insertions(+), 96 deletions(-) delete mode 100644 .nvmrc diff --git a/.nvmrc b/.nvmrc deleted file mode 100644 index b009dfb9d..000000000 --- a/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -lts/* diff --git a/src/servers/reducers.ts b/src/servers/reducers.ts index 3640f90ae..b4f0cab67 100644 --- a/src/servers/reducers.ts +++ b/src/servers/reducers.ts @@ -1,9 +1,9 @@ -import type { Reducer } from "redux"; +import type { Reducer } from 'redux'; -import { APP_SETTINGS_LOADED } from "../app/actions"; -import { DEEP_LINKS_SERVER_ADDED } from "../deepLinks/actions"; -import { OUTLOOK_CALENDAR_SAVE_CREDENTIALS } from "../outlookCalendar/actions"; -import type { ActionOf } from "../store/actions"; +import { APP_SETTINGS_LOADED } from '../app/actions'; +import { DEEP_LINKS_SERVER_ADDED } from '../deepLinks/actions'; +import { OUTLOOK_CALENDAR_SAVE_CREDENTIALS } from '../outlookCalendar/actions'; +import type { ActionOf } from '../store/actions'; import { ADD_SERVER_VIEW_SERVER_ADDED, SIDE_BAR_REMOVE_SERVER_CLICKED, @@ -26,16 +26,16 @@ import { WEBVIEW_SERVER_VERSION_UPDATED, SUPPORTED_VERSION_DIALOG_DISMISS, WEBVIEW_SIDEBAR_CUSTOM_THEME_CHANGED, -} from "../ui/actions"; -import { SERVERS_LOADED, SERVER_DOCUMENT_VIEWER_OPEN_URL } from "./actions"; -import type { Server } from "./common"; +} from '../ui/actions'; +import { SERVERS_LOADED, SERVER_DOCUMENT_VIEWER_OPEN_URL } from './actions'; +import type { Server } from './common'; const ensureUrlFormat = (serverUrl: string | null): string => { if (serverUrl) { return new URL(serverUrl).href; } - throw new Error("cannot handle null server URLs"); + throw new Error('cannot handle null server URLs'); }; type ServersActionTypes = @@ -64,7 +64,6 @@ type ServersActionTypes = | ActionOf | ActionOf | ActionOf - | ActionOf | ActionOf; const upsert = (state: Server[], server: Server): Server[] => { @@ -208,7 +207,7 @@ export const servers: Reducer = ( case SERVERS_LOADED: { const { servers = state } = action.payload; - return servers.map((server) => ({ + return servers.map((server: Server) => ({ ...server, url: ensureUrlFormat(server.url), })); @@ -216,9 +215,10 @@ export const servers: Reducer = ( case APP_SETTINGS_LOADED: { const { servers = state } = action.payload; - return servers.map((server) => ({ + return servers.map((server: Server) => ({ ...server, url: ensureUrlFormat(server.url), + documentViewerOpenUrl: '', })); } diff --git a/src/ui/components/ServersView/DocumentViewer.tsx b/src/ui/components/ServersView/DocumentViewer.tsx index 1da8666ba..cf001fe4a 100644 --- a/src/ui/components/ServersView/DocumentViewer.tsx +++ b/src/ui/components/ServersView/DocumentViewer.tsx @@ -1,66 +1,47 @@ import { Box, IconButton } from '@rocket.chat/fuselage'; -import { useState, useEffect } from 'react'; -const DynamicWebview = ({ +const DocumentViewer = ({ url, - isActive, partition, closeDocumentViewer, }: { url: string; - isActive: boolean; partition: string; closeDocumentViewer: () => void; }) => { - const [webView, setWebView] = useState(null); - - useEffect(() => { - if (isActive && url) { - setWebView( - - ); - } else { - setWebView(null); - } - }, [url, isActive, partition]); - return ( <> - {isActive && ( - - - -

PDF Viewer

-
+ + + +

PDF Viewer

+
- {webView} + + - )} +
); }; -export default DynamicWebview; +export default DocumentViewer; diff --git a/src/ui/components/ServersView/ServerPane.tsx b/src/ui/components/ServersView/ServerPane.tsx index e857be59a..54eb13077 100644 --- a/src/ui/components/ServersView/ServerPane.tsx +++ b/src/ui/components/ServersView/ServerPane.tsx @@ -1,19 +1,19 @@ -import { ipcRenderer } from "electron"; -import { useRef, useEffect, useState } from "react"; -import { useDispatch } from "react-redux"; -import type { Dispatch } from "redux"; +import { ipcRenderer } from 'electron'; +import { useRef, useEffect, useState } from 'react'; +import { useDispatch } from 'react-redux'; +import type { Dispatch } from 'redux'; -import { SERVER_DOCUMENT_VIEWER_OPEN_URL } from "../../../servers/actions"; -import type { RootAction } from "../../../store/actions"; +import { SERVER_DOCUMENT_VIEWER_OPEN_URL } from '../../../servers/actions'; +import type { RootAction } from '../../../store/actions'; import { LOADING_ERROR_VIEW_RELOAD_SERVER_CLICKED, WEBVIEW_ATTACHED, WEBVIEW_READY, -} from "../../actions"; -import DocumentViewer from "./DocumentViewer"; -import ErrorView from "./ErrorView"; -import UnsupportedServer from "./UnsupportedServer"; -import { StyledWebView, Wrapper } from "./styles"; +} from '../../actions'; +import DocumentViewer from './DocumentViewer'; +import ErrorView from './ErrorView'; +import UnsupportedServer from './UnsupportedServer'; +import { DocumentViewerWrapper, StyledWebView, Wrapper } from './styles'; type ServerPaneProps = { lastPath: string | undefined; @@ -38,7 +38,7 @@ export const ServerPane = ({ const [documentViewerActive, setDocumentViewerActive] = useState(false); const webviewRef = - useRef>(null); + useRef>(null); useEffect(() => { const webview = webviewRef.current; @@ -54,10 +54,10 @@ export const ServerPane = ({ if (webview) webview.focus(); }; - window.addEventListener("focus", handleWindowFocus); + window.addEventListener('focus', handleWindowFocus); return () => { - window.removeEventListener("focus", handleWindowFocus); + window.removeEventListener('focus', handleWindowFocus); }; }, [isFailed, isSelected, serverUrl]); @@ -68,7 +68,7 @@ export const ServerPane = ({ } let step = false; const addEventListenerOnce = ( - e: "did-attach" | "dom-ready", + e: 'did-attach' | 'dom-ready', cb: () => void ): void => { const handler = () => { @@ -91,12 +91,12 @@ export const ServerPane = ({ }, 300); step = true; }; - addEventListenerOnce("did-attach", handleAttachReady); - addEventListenerOnce("dom-ready", handleAttachReady); + addEventListenerOnce('did-attach', handleAttachReady); + addEventListenerOnce('dom-ready', handleAttachReady); return () => { - webview.removeEventListener("did-attach", handleAttachReady); - webview.removeEventListener("dom-ready", handleAttachReady); + webview.removeEventListener('did-attach', handleAttachReady); + webview.removeEventListener('dom-ready', handleAttachReady); }; }, [dispatch, serverUrl]); @@ -105,7 +105,7 @@ export const ServerPane = ({ if (!webview) { return; } - const addEventListenerOnce = (e: "did-attach", cb: () => void): void => { + const addEventListenerOnce = (e: 'did-attach', cb: () => void): void => { const handler = () => { cb(); webview.removeEventListener(e, handler); @@ -125,10 +125,10 @@ export const ServerPane = ({ }, 300); }; - addEventListenerOnce("did-attach", handleAttachReady); + addEventListenerOnce('did-attach', handleAttachReady); return () => { - webview.removeEventListener("did-attach", handleAttachReady); + webview.removeEventListener('did-attach', handleAttachReady); }; }, [dispatch, serverUrl]); @@ -149,7 +149,7 @@ export const ServerPane = ({ return; } - if (isSelected && documentViewerOpenUrl && documentViewerOpenUrl !== "") { + if (isSelected && documentViewerOpenUrl && documentViewerOpenUrl !== '') { setDocumentViewerActive(true); } else { setDocumentViewerActive(false); @@ -178,20 +178,20 @@ export const ServerPane = ({ const closeDocumentViewer = () => { dispatch({ type: SERVER_DOCUMENT_VIEWER_OPEN_URL, - payload: { server: serverUrl, documentUrl: "" }, + payload: { server: serverUrl, documentUrl: '' }, }); setDocumentViewerActive(false); }; useEffect(() => { const handleOnline = () => { - ipcRenderer.invoke("refresh-supported-versions", serverUrl); + ipcRenderer.invoke('refresh-supported-versions', serverUrl); }; - window.addEventListener("online", handleOnline); + window.addEventListener('online', handleOnline); return () => { - window.removeEventListener("online", handleOnline); + window.removeEventListener('online', handleOnline); }; }, [serverUrl]); @@ -201,14 +201,15 @@ export const ServerPane = ({ ref={webviewRef} isFailed={isFailed} partition={`persist:${serverUrl}`} - {...({ allowpopups: "allowpopups" } as any)} - />{" "} - + {...({ allowpopups: 'allowpopups' } as any)} + />{' '} + + + ` `}; `; +type DocumentViewerWrapperProps = { + isVisible: boolean; +}; + +export const DocumentViewerWrapper = styled.section` + ${({ isVisible }) => css` + display: ${isVisible ? 'flex' : 'none'}; + `}; +`; + type StyledWebViewProps = { isFailed: boolean; }; From 00f01c87f2d46977bce02fa4826fb86dcdd2bf9c Mon Sep 17 00:00:00 2001 From: Jean Brito Date: Thu, 8 Feb 2024 11:48:16 -0300 Subject: [PATCH 8/9] get from server the user theme appearance setting --- src/injected.ts | 15 +++++++++++++++ src/servers/common.ts | 1 + src/servers/preload/api.ts | 3 +++ src/servers/preload/themeAppearance.ts | 16 ++++++++++++++++ src/servers/reducers.ts | 9 ++++++++- src/ui/actions.ts | 6 ++++++ 6 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 src/servers/preload/themeAppearance.ts diff --git a/src/injected.ts b/src/injected.ts index 613d21073..6cd8d93d7 100644 --- a/src/injected.ts +++ b/src/injected.ts @@ -202,6 +202,21 @@ const start = async () => { window.RocketChatDesktop.setGitCommitHash(gitCommitHash); }); + Tracker.autorun(() => { + const uid = Meteor.userId(); + if (!uid) return; + const themeAppearance: string = getUserPreference(uid, 'themeAppearence'); + if ( + ['dark', 'light', 'auto', 'high-contrast'].includes( + themeAppearance as any + ) + ) { + window.RocketChatDesktop.setUserThemeAppearance( + themeAppearance as 'auto' | 'dark' | 'light' | 'high-contrast' + ); + } + }); + Tracker.autorun(() => { const uid = Meteor.userId(); if (!uid) return; diff --git a/src/servers/common.ts b/src/servers/common.ts index 843080340..c7fd698e0 100644 --- a/src/servers/common.ts +++ b/src/servers/common.ts @@ -26,6 +26,7 @@ export type Server = { supportedVersions?: SupportedVersions; expirationMessageLastTimeShown?: Date; documentViewerOpenUrl?: string; + themeAppearance?: 'dark' | 'light' | 'auto' | 'high-contrast'; }; export const enum ServerUrlResolutionStatus { diff --git a/src/servers/preload/api.ts b/src/servers/preload/api.ts index 40c6ee33d..03b0209a6 100644 --- a/src/servers/preload/api.ts +++ b/src/servers/preload/api.ts @@ -27,6 +27,7 @@ import { setServerVersionToSidebar, setSidebarCustomTheme, } from './sidebar'; +import { setUserThemeAppearance } from './themeAppearance'; import { setTitle } from './title'; import { setUrlResolver } from './urls'; import { setUserLoggedIn } from './userLoggedIn'; @@ -53,6 +54,7 @@ export type RocketChatDesktopAPI = { idleThreshold: number | null; setUserOnline: (online: boolean) => void; }) => void; + setUserThemeAppearance: (themeAppearance: Server['themeAppearance']) => void; createNotification: ( options: NotificationOptions & { canReply?: boolean; @@ -95,6 +97,7 @@ export const RocketChatDesktop: RocketChatDesktopAPI = { setTitle, setUserPresenceDetection, setUserLoggedIn, + setUserThemeAppearance, createNotification, destroyNotification, getInternalVideoChatWindowEnabled, diff --git a/src/servers/preload/themeAppearance.ts b/src/servers/preload/themeAppearance.ts new file mode 100644 index 000000000..c9a6a864c --- /dev/null +++ b/src/servers/preload/themeAppearance.ts @@ -0,0 +1,16 @@ +import { dispatch } from '../../store'; +import { WEBVIEW_USER_THEME_APPEARANCE_CHANGED } from '../../ui/actions'; +import type { Server } from '../common'; +import { getServerUrl } from './urls'; + +export const setUserThemeAppearance = ( + themeAppearance: Server['themeAppearance'] +): void => { + dispatch({ + type: WEBVIEW_USER_THEME_APPEARANCE_CHANGED, + payload: { + url: getServerUrl(), + themeAppearance, + }, + }); +}; diff --git a/src/servers/reducers.ts b/src/servers/reducers.ts index b4f0cab67..33b9f6990 100644 --- a/src/servers/reducers.ts +++ b/src/servers/reducers.ts @@ -26,6 +26,7 @@ import { WEBVIEW_SERVER_VERSION_UPDATED, SUPPORTED_VERSION_DIALOG_DISMISS, WEBVIEW_SIDEBAR_CUSTOM_THEME_CHANGED, + WEBVIEW_USER_THEME_APPEARANCE_CHANGED, } from '../ui/actions'; import { SERVERS_LOADED, SERVER_DOCUMENT_VIEWER_OPEN_URL } from './actions'; import type { Server } from './common'; @@ -64,7 +65,8 @@ type ServersActionTypes = | ActionOf | ActionOf | ActionOf - | ActionOf; + | ActionOf + | ActionOf; const upsert = (state: Server[], server: Server): Server[] => { const index = state.findIndex(({ url }) => url === server.url); @@ -137,6 +139,11 @@ export const servers: Reducer = ( return upsert(state, { url, uniqueID }); } + case WEBVIEW_USER_THEME_APPEARANCE_CHANGED: { + const { url, themeAppearance } = action.payload; + return upsert(state, { url, themeAppearance }); + } + case WEBVIEW_SERVER_IS_SUPPORTED_VERSION: { const { url, isSupportedVersion } = action.payload; return upsert(state, { url, isSupportedVersion }); diff --git a/src/ui/actions.ts b/src/ui/actions.ts index 49a58a9ab..cefcbcba5 100644 --- a/src/ui/actions.ts +++ b/src/ui/actions.ts @@ -65,6 +65,8 @@ export const WEBVIEW_GIT_COMMIT_HASH_CHECK = 'webview/git-commit-hash-check'; export const WEBVIEW_TITLE_CHANGED = 'webview/title-changed'; export const WEBVIEW_UNREAD_CHANGED = 'webview/unread-changed'; export const WEBVIEW_USER_LOGGED_IN = 'webview/user-loggedin'; +export const WEBVIEW_USER_THEME_APPEARANCE_CHANGED = + 'webview/user-theme-appearance-changed'; export const WEBVIEW_ALLOWED_REDIRECTS_CHANGED = 'webview/allowed-redirects-changed'; export const SETTINGS_SET_REPORT_OPT_IN_CHANGED = @@ -159,6 +161,10 @@ export type UiActionTypeToPayloadMap = { url: Server['url']; userLoggedIn: Server['userLoggedIn']; }; + [WEBVIEW_USER_THEME_APPEARANCE_CHANGED]: { + url: Server['url']; + themeAppearance: Server['themeAppearance']; + }; [WEBVIEW_GIT_COMMIT_HASH_CHECK]: { url: Server['url']; gitCommitHash: Server['gitCommitHash']; From bfccbd4e5f1ebcf2add4e5f92f2866ec6b45ba09 Mon Sep 17 00:00:00 2001 From: Jean Brito Date: Thu, 8 Feb 2024 12:15:51 -0300 Subject: [PATCH 9/9] documentViewer reflects themeAppearance now --- .../components/ServersView/DocumentViewer.tsx | 24 ++++++++++++++++--- src/ui/components/ServersView/ServerPane.tsx | 3 +++ src/ui/components/ServersView/index.tsx | 1 + 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/ui/components/ServersView/DocumentViewer.tsx b/src/ui/components/ServersView/DocumentViewer.tsx index cf001fe4a..4a0eb33f1 100644 --- a/src/ui/components/ServersView/DocumentViewer.tsx +++ b/src/ui/components/ServersView/DocumentViewer.tsx @@ -1,26 +1,44 @@ import { Box, IconButton } from '@rocket.chat/fuselage'; +import { useDarkMode } from '@rocket.chat/fuselage-hooks'; const DocumentViewer = ({ url, partition, closeDocumentViewer, + themeAppearance, }: { url: string; partition: string; + themeAppearance: string | undefined; closeDocumentViewer: () => void; }) => { + const theme = useDarkMode( + themeAppearance === 'auto' ? undefined : themeAppearance === 'dark' + ) + ? 'dark' + : 'light'; return ( <> - - + +

PDF Viewer

diff --git a/src/ui/components/ServersView/ServerPane.tsx b/src/ui/components/ServersView/ServerPane.tsx index 54eb13077..d2dbacfa3 100644 --- a/src/ui/components/ServersView/ServerPane.tsx +++ b/src/ui/components/ServersView/ServerPane.tsx @@ -23,6 +23,7 @@ type ServerPaneProps = { isSupported: boolean | undefined; title: string | undefined; documentViewerOpenUrl: string | undefined; + themeAppearance: string | undefined; }; export const ServerPane = ({ @@ -32,6 +33,7 @@ export const ServerPane = ({ isFailed, isSupported, documentViewerOpenUrl, + themeAppearance, }: ServerPaneProps) => { const dispatch = useDispatch>(); @@ -208,6 +210,7 @@ export const ServerPane = ({ url={documentViewerOpenUrl || ''} partition={`persist:${serverUrl}`} closeDocumentViewer={closeDocumentViewer} + themeAppearance={themeAppearance} /> { isSupported={server.isSupportedVersion} title={server.title} documentViewerOpenUrl={server.documentViewerOpenUrl} + themeAppearance={server.themeAppearance} /> ))}