Skip to content

Commit

Permalink
chore: Add PDF viewer (#2796)
Browse files Browse the repository at this point in the history
* open PDF viewer above the chat webview


---------

Co-authored-by: gabriellsh <gabriel.henriques@rocket.chat>
Co-authored-by: Tasso Evangelista <tasso.evangelista@rocket.chat>
  • Loading branch information
3 people authored Feb 9, 2024
1 parent 11e89ae commit d64e820
Show file tree
Hide file tree
Showing 19 changed files with 234 additions and 12 deletions.
1 change: 0 additions & 1 deletion .nvmrc

This file was deleted.

29 changes: 29 additions & 0 deletions src/documentViewer/ipc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
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;
}
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 },
});
}
);
};
15 changes: 15 additions & 0 deletions src/injected.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions src/ipc/channels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ type ChannelToArgsMap = {
'outlook-calendar/has-credentials': () => Promise<boolean>;
'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;
Expand Down
2 changes: 2 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -98,6 +99,7 @@ const start = async (): Promise<void> => {
handleJitsiDesktopCapturerGetSources();
handleDesktopCapturerGetSources();
startOutlookCalendarUrlHandler();
startDocumentViewerHandler();
checkSupportedVersionServers();

await processDeepLinksInArgs();
Expand Down
3 changes: 1 addition & 2 deletions src/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ declare global {
}

contextBridge.exposeInMainWorld('JitsiMeetElectron', JitsiMeetElectron);
contextBridge.exposeInMainWorld('RocketChatDesktop', RocketChatDesktop);

const start = async (): Promise<void> => {
console.log('[Rocket.Chat Desktop] preload.ts start');
Expand All @@ -36,8 +37,6 @@ const start = async (): Promise<void> => {

window.removeEventListener('load', start);

contextBridge.exposeInMainWorld('RocketChatDesktop', RocketChatDesktop);

setServerUrl(serverUrl);

await whenReady();
Expand Down
6 changes: 6 additions & 0 deletions src/servers/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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]: {
Expand All @@ -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;
};
};
2 changes: 2 additions & 0 deletions src/servers/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export type Server = {
supportedVersionsSource?: 'server' | 'cloud' | 'builtin';
supportedVersions?: SupportedVersions;
expirationMessageLastTimeShown?: Date;
documentViewerOpenUrl?: string;
themeAppearance?: 'dark' | 'light' | 'auto' | 'high-contrast';
};

export const enum ServerUrlResolutionStatus {
Expand Down
6 changes: 6 additions & 0 deletions src/servers/preload/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -26,6 +27,7 @@ import {
setServerVersionToSidebar,
setSidebarCustomTheme,
} from './sidebar';
import { setUserThemeAppearance } from './themeAppearance';
import { setTitle } from './title';
import { setUrlResolver } from './urls';
import { setUserLoggedIn } from './userLoggedIn';
Expand All @@ -52,6 +54,7 @@ export type RocketChatDesktopAPI = {
idleThreshold: number | null;
setUserOnline: (online: boolean) => void;
}) => void;
setUserThemeAppearance: (themeAppearance: Server['themeAppearance']) => void;
createNotification: (
options: NotificationOptions & {
canReply?: boolean;
Expand All @@ -72,6 +75,7 @@ export type RocketChatDesktopAPI = {
hasOutlookCredentials: () => Promise<boolean>;
clearOutlookCredentials: () => void;
setUserToken: (token: string, userId: string) => void;
openDocumentViewer: (url: string, format: string, options: any) => void;
};

export const RocketChatDesktop: RocketChatDesktopAPI = {
Expand All @@ -93,6 +97,7 @@ export const RocketChatDesktop: RocketChatDesktopAPI = {
setTitle,
setUserPresenceDetection,
setUserLoggedIn,
setUserThemeAppearance,
createNotification,
destroyNotification,
getInternalVideoChatWindowEnabled,
Expand All @@ -105,4 +110,5 @@ export const RocketChatDesktop: RocketChatDesktopAPI = {
clearOutlookCredentials,
setUserToken,
setSidebarCustomTheme,
openDocumentViewer,
};
9 changes: 9 additions & 0 deletions src/servers/preload/documentViewer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { ipcRenderer } from 'electron';

export const openDocumentViewer = (
url: string,
format: string,
options: any
): void => {
ipcRenderer.invoke('document-viewer/open-window', url, format, options);
};
16 changes: 16 additions & 0 deletions src/servers/preload/themeAppearance.ts
Original file line number Diff line number Diff line change
@@ -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,
},
});
};
22 changes: 18 additions & 4 deletions src/servers/reducers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ 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 } from './actions';
import { SERVERS_LOADED, SERVER_DOCUMENT_VIEWER_OPEN_URL } from './actions';
import type { Server } from './common';

const ensureUrlFormat = (serverUrl: string | null): string => {
Expand Down Expand Up @@ -63,7 +64,9 @@ type ServersActionTypes =
| ActionOf<typeof WEBVIEW_SERVER_UNIQUE_ID_UPDATED>
| ActionOf<typeof WEBVIEW_SERVER_IS_SUPPORTED_VERSION>
| ActionOf<typeof WEBVIEW_SERVER_VERSION_UPDATED>
| ActionOf<typeof SUPPORTED_VERSION_DIALOG_DISMISS>;
| ActionOf<typeof SUPPORTED_VERSION_DIALOG_DISMISS>
| ActionOf<typeof SERVER_DOCUMENT_VIEWER_OPEN_URL>
| ActionOf<typeof WEBVIEW_USER_THEME_APPEARANCE_CHANGED>;

const upsert = (state: Server[], server: Server): Server[] => {
const index = state.findIndex(({ url }) => url === server.url);
Expand Down Expand Up @@ -136,6 +139,11 @@ export const servers: Reducer<Server[], ServersActionTypes> = (
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 });
Expand Down Expand Up @@ -206,17 +214,18 @@ export const servers: Reducer<Server[], ServersActionTypes> = (

case SERVERS_LOADED: {
const { servers = state } = action.payload;
return servers.map((server) => ({
return servers.map((server: Server) => ({
...server,
url: ensureUrlFormat(server.url),
}));
}

case APP_SETTINGS_LOADED: {
const { servers = state } = action.payload;
return servers.map((server) => ({
return servers.map((server: Server) => ({
...server,
url: ensureUrlFormat(server.url),
documentViewerOpenUrl: '',
}));
}

Expand All @@ -235,6 +244,11 @@ export const servers: Reducer<Server[], ServersActionTypes> = (
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;
}
Expand Down
6 changes: 6 additions & 0 deletions src/ui/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down Expand Up @@ -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'];
Expand Down
65 changes: 65 additions & 0 deletions src/ui/components/ServersView/DocumentViewer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
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 (
<>
<Box
bg={theme}
width='100%'
height='100%'
position='absolute'
content='center'
alignItems='center'
>
<Box
content='center'
alignItems='center'
display='flex'
color={theme === 'dark' ? 'font-white' : 'font-text'}
>
<IconButton
icon='arrow-back'
onClick={closeDocumentViewer}
mi='x8'
color={theme === 'dark' ? 'white' : 'default'}
/>
<h2>PDF Viewer</h2>
</Box>

<Box>
<webview
src={url}
style={{
width: '100%',
height: '100%',
position: 'absolute',
left: 0,
top: 50,
right: 0,
bottom: 0,
}}
partition={partition}
/>
</Box>
</Box>
</>
);
};

export default DocumentViewer;
Loading

0 comments on commit d64e820

Please sign in to comment.