Skip to content

Commit

Permalink
Fixed a mouse clicking issue
Browse files Browse the repository at this point in the history
  • Loading branch information
ChiaMineJP committed Sep 30, 2024
1 parent fa2a996 commit bbdbb1a
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 45 deletions.
57 changes: 45 additions & 12 deletions packages/core/src/components/Button/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { alpha, Button as BaseButton, ButtonProps as BaseButtonProps } from '@mui/material';
import React from 'react';
import React, { SyntheticEvent } from 'react';
import { useNavigate } from 'react-router-dom';
import styled from 'styled-components';

Expand Down Expand Up @@ -53,24 +53,57 @@ export default function Button(props: ButtonProps) {

const navigate = useNavigate();

function handleClick(...args) {
if (to) {
navigate(to);
}
const handleClick = React.useCallback(
(...args: any[]) => {
if (to) {
navigate(to);
}

if (onClick) {
onClick(...args);
}
},
[to, navigate, onClick],
);

if (onClick) {
onClick(...args);
const onAuxClick = React.useMemo(() => {
if (!rest.href) {
return undefined;
}
}
return (event: SyntheticEvent, ...restArgs: any[]) => {
event.preventDefault();
handleClick(...restArgs);
};
}, [rest.href, handleClick]);

switch (color) {
case 'danger':
return <DangerButton onClick={handleClick} disableElevation={disableElevation} {...rest} />;
return (
<DangerButton {...rest} onClick={handleClick} onAuxClick={onAuxClick} disableElevation={disableElevation} />
);
case 'primary':
return <StyledBaseButton onClick={handleClick} disableElevation={disableElevation} color="primary" {...rest} />;
return (
<StyledBaseButton
{...rest}
onClick={handleClick}
onAuxClick={onAuxClick}
disableElevation={disableElevation}
color="primary"
/>
);
case 'secondary':
return <StyledBaseButton onClick={handleClick} disableElevation={disableElevation} color="secondary" {...rest} />;
return (
<StyledBaseButton
{...rest}
onClick={handleClick}
onAuxClick={onAuxClick}
disableElevation={disableElevation}
color="secondary"
/>
);
default:
return <StyledBaseButton onClick={handleClick} disableElevation={disableElevation} {...rest} />;
return (
<StyledBaseButton {...rest} onClick={handleClick} onAuxClick={onAuxClick} disableElevation={disableElevation} />
);
}
}
14 changes: 11 additions & 3 deletions packages/core/src/components/Link/Link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,27 @@ export default function Link(props: Props) {
};

function handleClick(event: SyntheticEvent) {
event.preventDefault();

if (onClick) {
event.preventDefault();
event.stopPropagation();
onClick(event);
return;
}

if (href && target === '_blank') {
event.preventDefault();
event.stopPropagation();
openExternal(href);
}
}

return <StyledBaseLink component={to ? RouterLink : BaseLink} {...newProps} onClick={handleClick} />;
// `onAuxClick` is used to handle middle mouse click as well as other mouse buttons.
return (
<StyledBaseLink
component={to ? RouterLink : BaseLink}
{...newProps}
onClick={handleClick}
onAuxClick={handleClick}
/>
);
}
39 changes: 26 additions & 13 deletions packages/core/src/components/MenuItem/MenuItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,34 @@ function MenuItem(props: MenuItemProps, ref: any) {

const menuContext: MenuContextInterface | undefined = useContext(MenuContext);

async function handleClick(event: React.MouseEvent<HTMLLIElement>) {
event.stopPropagation();

if (close === true) {
menuContext?.close(event, 'menuItemClick');
const handleClick = React.useCallback(
async (event: React.MouseEvent<HTMLLIElement>) => {
event.stopPropagation();

if (close === true) {
menuContext?.close(event, 'menuItemClick');
}

await onClick?.(event);

if (close === 'after') {
menuContext?.close(event, 'menuItemClick');
}
},
[close, menuContext, onClick],
);

const onAuxClick = React.useMemo(() => {
if (!rest.href) {
return undefined;
}
return (event: React.MouseEvent<HTMLLIElement>) => {
event.preventDefault();
return handleClick(event);
};
}, [rest.href, handleClick]);

await onClick?.(event);

if (close === 'after') {
menuContext?.close(event, 'menuItemClick');
}
}

const item = <BaseMenuItem {...rest} onClick={handleClick} ref={ref} />;
const item = <BaseMenuItem {...rest} onClick={handleClick} onAuxClick={onAuxClick} ref={ref} />;

if (tooltip) {
return <Tooltip title={tooltip}>{item}</Tooltip>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Flex, Link, DialogActions } from '@chia-network/core';
import { Trans } from '@lingui/macro';
import { Button, Dialog, DialogContent, DialogTitle, Typography } from '@mui/material';
import React from 'react';
import isURL from 'validator/es/lib/isURL';

import useOpenUnsafeLink from '../../hooks/useOpenUnsafeLink';

Expand All @@ -15,17 +16,30 @@ export default function NotificationAnnouncementDialog(props: NotificationAnnoun

const openUnsafeLink = useOpenUnsafeLink();

function handleClose() {
const handleClose = React.useCallback(() => {
onClose?.(false);
}
}, [onClose]);

const message = 'message' in notification ? notification.message : undefined;
const url = 'url' in notification ? notification.url : undefined;
const url = 'url' in notification && typeof notification.url === 'string' ? notification.url : undefined;
const from = 'from' in notification ? notification.from : undefined;

async function handleURLClick() {
const handleURLClick = React.useCallback(() => {
if (!url) {
return;
}
openUnsafeLink(url);
}
}, [url, openUnsafeLink]);

const urlLabel = React.useMemo(() => {
if (!url) {
return undefined;
}
if (!isURL(url)) {
return <Trans>##### Redacted for security reason #####</Trans>;
}
return url;
}, [url]);

return (
<Dialog onClose={handleClose} maxWidth="sm" fullWidth open>
Expand Down Expand Up @@ -62,9 +76,7 @@ export default function NotificationAnnouncementDialog(props: NotificationAnnoun
<Trans>URL</Trans>
</Typography>
<Typography>
<Link href={url} target="_blank" onClick={handleURLClick}>
{url}
</Link>
<Link onClick={handleURLClick}>{urlLabel}</Link>
</Typography>
</Flex>
) : null}
Expand Down
20 changes: 12 additions & 8 deletions packages/gui/src/electron/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import React from 'react';
// import os from 'os';
import ReactDOMServer from 'react-dom/server';
import { ServerStyleSheet, StyleSheetManager } from 'styled-components';
import isURL from 'validator/es/lib/isURL';

// handle setupevents as quickly as possible
import '../config/env';
Expand All @@ -40,6 +41,16 @@ import { readAddressBook, saveAddressBook } from './addressBook';
import installDevTools from './installDevTools.dev';
import { readPrefs, savePrefs, migratePrefs } from './prefs';

/**
* Open the given external protocol URL in the desktop’s default manner.
*/
function openExternal(urlLocal: string) {
if (!isURL(urlLocal, { protocols: ['http', 'https', 'ipfs'], require_protocol: true })) {
return;
}
shell.openExternal(urlLocal);
}

const isPlaywrightTesting = process.env.PLAYWRIGHT_TESTS === 'true';
const NET = 'mainnet';

Expand Down Expand Up @@ -111,7 +122,7 @@ function openAbout() {
aboutWindow.loadURL(`data:text/html;charset=utf-8,${about}`);

aboutWindow.webContents.setWindowOpenHandler((details) => {
shell.openExternal(details.url);
openExternal(details.url);
return { action: 'deny' };
});

Expand Down Expand Up @@ -910,10 +921,3 @@ function getMenuTemplate() {

return template;
}

/**
* Open the given external protocol URL in the desktop’s default manner.
*/
function openExternal(urlLocal) {
shell.openExternal(urlLocal);
}
40 changes: 39 additions & 1 deletion packages/gui/src/hooks/useOpenUnsafeLink.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,42 @@
import { usePrefs } from '@chia-network/api-react';
import { ConfirmDialog, CopyToClipboard, Flex, useOpenDialog, useOpenExternal } from '@chia-network/core';
import { AlertDialog, ConfirmDialog, CopyToClipboard, Flex, useOpenDialog, useOpenExternal } from '@chia-network/core';
import { Trans } from '@lingui/macro';
import { Checkbox, FormControlLabel, InputAdornment, TextField, Typography } from '@mui/material';
import React from 'react';
import isURL from 'validator/es/lib/isURL';

/* ========================================================================== */

const SuppressUnsafeLinkWarningLocalStorageKey = 'suppressUnsafeLinkWarning';

/* ========================================================================== */
type InvalidURLWarningDialogProps = {
url: string;
};

function InvalidURLWarningDialog(props: InvalidURLWarningDialogProps) {
const { url, ...rest } = props;

return (
<AlertDialog {...rest} title={<Trans>Warning: Invalid URL</Trans>}>
<Flex flexDirection="column" gap={2}>
<Typography>
<Trans>This type of the URL is not allowed to open for security reasons.</Trans>
</Typography>
<TextField
label={<Trans>URL</Trans>}
value={url}
variant="filled"
InputProps={{
readOnly: true,
}}
fullWidth
/>
</Flex>
</AlertDialog>
);
}

/* ========================================================================== */

type OpenUnsafeLinkConfirmationDialogProps = {
Expand Down Expand Up @@ -78,6 +107,15 @@ export default function useOpenUnsafeLink() {
async function openUnsafeLink(url: string) {
let openUrl = false;

if (!url) {
return;
}

if (!isURL(url)) {
await openDialog(<InvalidURLWarningDialog url={url} />);
return;
}

if (suppressUnsafeLinkWarning) {
openUrl = true;
} else {
Expand Down

0 comments on commit bbdbb1a

Please sign in to comment.