Add tooltips and helper buttons

This commit is contained in:
Reckless_Satoshi 2022-05-24 06:33:55 -07:00
parent d492475eec
commit 83564df25a
No known key found for this signature in database
GPG Key ID: 9C4585B561315571
3 changed files with 136 additions and 121 deletions

View File

@ -14,7 +14,7 @@ import {
Link,
} from "@mui/material"
import { saveAsJson, saveAsTxt } from "../../utils/saveFile";
import { saveAsJson } from "../../utils/saveFile";
// Icons
import KeyIcon from '@mui/icons-material/Key';
@ -53,120 +53,130 @@ const AuditPGPDialog = ({
onClose={onClose}
>
<DialogTitle >
{t("This chat is PGP Encrypted")}
{t("Do not trust, verify!")}
</DialogTitle>
<DialogContent>
<DialogContentText>
{t("Your communication is end-to-end encrypted with OpenPGP. You can verify the privacy of this chat using any third party tool based on the OpenPGP standard.")}
{t("Your communication is end-to-end encrypted with OpenPGP. You can verify the privacy of this chat using any tool based on the OpenPGP standard.")}
</DialogContentText>
<Grid container spacing={1} align="center">
<Grid item align="center" xs={12}>
<Button component={Link} target="_blank" href="https://learn.robosats.com/docs/pgp-encryption">{t("Learn how to audit")}</Button>
<Button component={Link} target="_blank" href="https://learn.robosats.com/docs/pgp-encryption">{t("Learn how to verify")}</Button>
</Grid>
<Grid item align="center" xs={12}>
<TextField
sx={{width:"100%", maxWidth:"550px"}}
disabled
label={<b>{t("Your public key")}</b>}
value={own_pub_key}
variant='filled'
size='small'
InputProps={{
endAdornment:
<Tooltip disableHoverListener enterTouchDelay={0} title={t("Copied!")}>
<IconButton onClick={()=> navigator.clipboard.writeText(own_pub_key)}>
<ContentCopy/>
</IconButton>
</Tooltip>,
}}
/>
<Tooltip placement="top" enterTouchDelay={0} enterDelay={0} title={t("Your PGP public key. Your peer uses it to encrypt messages only you can read.")}>
<TextField
sx={{width:"100%", maxWidth:"550px"}}
disabled
label={<b>{t("Your public key")}</b>}
value={own_pub_key}
variant='filled'
size='small'
InputProps={{
endAdornment:
<Tooltip disableHoverListener enterTouchDelay={0} title={t("Copied!")}>
<IconButton onClick={()=> navigator.clipboard.writeText(own_pub_key)}>
<ContentCopy/>
</IconButton>
</Tooltip>,
}}
/>
</Tooltip>
</Grid>
<Grid item align="center" xs={12}>
<TextField
sx={{width:"100%", maxWidth:"550px"}}
disabled
label={<b>{t("Peer public key")}</b>}
value={peer_pub_key}
variant='filled'
size='small'
InputProps={{
endAdornment:
<Tooltip disableHoverListener enterTouchDelay={0} title={t("Copied!")}>
<IconButton onClick={()=> navigator.clipboard.writeText(peer_pub_key)}>
<ContentCopy/>
</IconButton>
</Tooltip>,
}}
/>
<Tooltip placement="top" enterTouchDelay={0} enterDelay={0} title={t("Your peer PGP public key. You use it to encrypt messages only he can read.and to verify your peer signed the incoming messages.")}>
<TextField
sx={{width:"100%", maxWidth:"550px"}}
disabled
label={<b>{t("Peer public key")}</b>}
value={peer_pub_key}
variant='filled'
size='small'
InputProps={{
endAdornment:
<Tooltip disableHoverListener enterTouchDelay={0} title={t("Copied!")}>
<IconButton onClick={()=> navigator.clipboard.writeText(peer_pub_key)}>
<ContentCopy/>
</IconButton>
</Tooltip>,
}}
/>
</Tooltip>
</Grid>
<Grid item align="center" xs={12}>
<TextField
sx={{width:"100%", maxWidth:"550px"}}
disabled
label={<b>{t("Your encrypted private key")}</b>}
value={own_enc_priv_key}
variant='filled'
size='small'
InputProps={{
endAdornment:
<Tooltip disableHoverListener enterTouchDelay={0} title={t("Copied!")}>
<IconButton onClick={()=> navigator.clipboard.writeText(own_enc_priv_key)}>
<ContentCopy/>
</IconButton>
</Tooltip>,
}}
/>
<Tooltip placement="top" enterTouchDelay={0} enterDelay={0} title={t("Your encrypted private key. You use it to decrypt the messages that your peer encrypted for you. You also use it to sign the messages you send.")}>
<TextField
sx={{width:"100%", maxWidth:"550px"}}
disabled
label={<b>{t("Your encrypted private key")}</b>}
value={own_enc_priv_key}
variant='filled'
size='small'
InputProps={{
endAdornment:
<Tooltip disableHoverListener enterTouchDelay={0} title={t("Copied!")}>
<IconButton onClick={()=> navigator.clipboard.writeText(own_enc_priv_key)}>
<ContentCopy/>
</IconButton>
</Tooltip>,
}}
/>
</Tooltip>
</Grid>
<Grid item align="center" xs={12}>
<TextField
sx={{width:"100%", maxWidth:"550px"}}
disabled
label={<b>{t("Your private key passphrase (keep secure!)")}</b>}
value={passphrase}
variant='filled'
size='small'
InputProps={{
endAdornment:
<Tooltip disableHoverListener enterTouchDelay={0} title={t("Copied!")}>
<IconButton onClick={()=> navigator.clipboard.writeText(passphrase)}>
<ContentCopy/>
</IconButton>
</Tooltip>,
}}
/>
<Tooltip placement="top" enterTouchDelay={0} enterDelay={0} title={t("The passphrase to decrypt your private key. Only you know it! Do not share. It is also your robot avatar user token.")}>
<TextField
sx={{width:"100%", maxWidth:"550px"}}
disabled
label={<b>{t("Your private key passphrase (keep secure!)")}</b>}
value={passphrase}
variant='filled'
size='small'
InputProps={{
endAdornment:
<Tooltip disableHoverListener enterTouchDelay={0} title={t("Copied!")}>
<IconButton onClick={()=> navigator.clipboard.writeText(passphrase)}>
<ContentCopy/>
</IconButton>
</Tooltip>,
}}
/>
</Tooltip>
</Grid>
<br/>
<Grid item xs={6}>
<Button
size="small"
color="primary"
variant="contained"
onClick={()=>saveAsJson(
'keys_'+orderId+'.json',
{"own_public_key": own_pub_key,
"peer_public_key":peer_pub_key,
"encrypted_private_key":own_enc_priv_key,
"passphrase":passphrase
})}>
<div style={{width:26,height:18}}>
<ExportIcon sx={{width:18,height:18}}/>
</div>
{t("Keys")}
<div style={{width:26,height:20}}>
<KeyIcon sx={{width:20,height:20}}/>
</div>
</Button>
<Tooltip placement="top" enterTouchDelay={0} enterDelay={1000} enterNextDelay={2000} title={t("Save credentials as a JSON file")}>
<Button
size="small"
color="primary"
variant="contained"
onClick={()=>saveAsJson(
'keys_'+orderId+'.json',
{"own_public_key": own_pub_key,
"peer_public_key":peer_pub_key,
"encrypted_private_key":own_enc_priv_key,
"passphrase":passphrase
})}>
<div style={{width:26,height:18}}>
<ExportIcon sx={{width:18,height:18}}/>
</div>
{t("Keys")}
<div style={{width:26,height:20}}>
<KeyIcon sx={{width:20,height:20}}/>
</div>
</Button>
</Tooltip>
</Grid>
<Grid item xs={6}>
{/* <ToolTip placement="top" enterTouchDelay={0} enterDelay={1000} enterNextDelay={2000} title={t("Save local messages and credentials as a JSON file")}> */}
<Tooltip placement="top" enterTouchDelay={0} enterDelay={1000} enterNextDelay={2000} title={t("Save messages as a JSON file")}>
<Button
size="small"
color="primary"
@ -182,7 +192,7 @@ const AuditPGPDialog = ({
<ForumIcon sx={{width:20,height:20}}/>
</div>
</Button>
{/* </ToolTip> */}
</Tooltip>
</Grid>

View File

@ -1,16 +1,16 @@
import React, { Component } from 'react';
import { withTranslation } from "react-i18next";
import {Button, Badge, Tooltip, TextField, Grid, Container, Card, CardHeader, Paper, Avatar, Typography} from "@mui/material";
import {Button, IconButton, Badge, Tooltip, TextField, Grid, Container, Card, CardHeader, Paper, Avatar, Typography} from "@mui/material";
import ReconnectingWebSocket from 'reconnecting-websocket';
import { encryptMessage , decryptMessage} from "../utils/pgp";
import { getCookie } from "../utils/cookies";
import { saveAsJson, saveAsTxt } from "../utils/saveFile";
import { saveAsJson } from "../utils/saveFile";
import { AuditPGPDialog } from "./Dialogs"
// Icons
import CheckIcon from '@mui/icons-material/Check';
import CloseIcon from '@mui/icons-material/Close';
import FileDownloadIcon from '@mui/icons-material/FileDownload';
import ContentCopy from "@mui/icons-material/ContentCopy";
import VisibilityIcon from '@mui/icons-material/Visibility';
import KeyIcon from '@mui/icons-material/Key';
import { ExportIcon } from './Icons';
@ -193,7 +193,24 @@ class Chat extends Component {
</Badge>
}
style={{backgroundColor: '#eeeeee'}}
title={<div style={{display:'flex',alignItems:'center', flexWrap:'wrap'}}>{message.userNick}{message.validSignature ? <CheckIcon sx={{height:16, display: "inline-block"}} color="success"/> : <CloseIcon sx={{height:16, display:"inline-block"}} color="error"/> }</div>}
title={
<Tooltip placement="top" enterTouchDelay={0} enterDelay={500} enterNextDelay={2000} title={t(message.validSignature ? "Verified signature by {{nickname}}": "Invalid signature! Not sent by {{nickname}}",{"nickname": message.userNick})}>
<div style={{display:'flex',alignItems:'center', flexWrap:'wrap'}}>
{message.userNick}
{message.validSignature ?
<CheckIcon sx={{height:16}} color="success"/>
:
<CloseIcon sx={{height:16}} color="error"/>
}
<div style={{width:20}}>
<IconButton sx={{height:16}}><VisibilityIcon sx={{height:16}}/></IconButton>
</div>
<div style={{width:20}}>
<IconButton sx={{height:16}}><ContentCopy sx={{height:16}}/></IconButton>
</div>
</div>
</Tooltip>
}
subheader={this.state.audit ? message.encryptedMessage : message.plainTextMessage}
subheaderTypographyProps={{sx: {wordWrap: "break-word", width: '200px', color: '#444444'}}}
/>
@ -209,15 +226,21 @@ class Chat extends Component {
}
style={{backgroundColor: '#fafafa'}}
title={
<Tooltip placement="top" enterTouchDelay={0} enterDelay={500} enterNextDelay={2000} title={t(message.validSignature ? "Verified signature by {{sender}}": "Invalid signature",{"sender": message.userNick})}>
<div style={{display:'flex',alignItems:'center', flexWrap:'wrap'}}>
{message.userNick}
{message.validSignature ?
<CheckIcon sx={{height:16, display: "inline-block"}} color="success"/>
:
<CloseIcon sx={{height:16, display:"inline-block"}} color="error"/>
}
</div>
<Tooltip placement="top" enterTouchDelay={0} enterDelay={500} enterNextDelay={2000} title={t(message.validSignature ? "Verified signature by {{nickname}}": "Invalid signature! Not sent by {{nickname}}",{"nickname": message.userNick})}>
<div style={{display:'flex',alignItems:'center', flexWrap:'wrap'}}>
{message.userNick}
{message.validSignature ?
<CheckIcon sx={{height:16}} color="success"/>
:
<CloseIcon sx={{height:16}} color="error"/>
}
<div style={{width:20}}>
<IconButton sx={{height:16}}><VisibilityIcon sx={{height:16}}/></IconButton>
</div>
<div style={{width:20}}>
<IconButton sx={{height:16}}><ContentCopy sx={{height:16}}/></IconButton>
</div>
</div>
</Tooltip>}
subheader={this.state.audit ? message.encryptedMessage : message.plainTextMessage}
subheaderTypographyProps={{sx: {wordWrap: "break-word", width: '200px', color: '#444444'}}}
@ -268,7 +291,7 @@ class Chat extends Component {
</Grid>
<Grid item xs={6}>
<Tooltip placement="bottom" enterTouchDelay={0} enterDelay={500} enterNextDelay={2000} title={t("Save messages and credentials as a JSON file")}>
<Tooltip placement="bottom" enterTouchDelay={0} enterDelay={500} enterNextDelay={2000} title={t("Save full log as a JSON file (messages and credentials)")}>
<Button size="small" color="primary" variant="outlined" onClick={()=>saveAsJson('chat_'+this.props.orderId+'.json', this.createJsonFile())}><div style={{width:28,height:20}}><ExportIcon sx={{width:20,height:20}}/></div> {t("Export")} </Button>
</Tooltip>
</Grid>

View File

@ -3,24 +3,6 @@
* @param {filename} data -- object to save
*/
export const saveAsTxt = (filename, dataObjToWrite) => {
const blob = new Blob([JSON.stringify(dataObjToWrite, null, 2)], { type: "text/plain;charset=utf8" });
const link = document.createElement("a");
link.download = filename;
link.href = window.URL.createObjectURL(blob);
link.dataset.downloadurl = ["text/plain;charset=utf8", link.download, link.href].join(":");
const evt = new MouseEvent("click", {
view: window,
bubbles: true,
cancelable: true,
});
link.dispatchEvent(evt);
link.remove()
};
export const saveAsJson = (filename, dataObjToWrite) => {
const blob = new Blob([JSON.stringify(dataObjToWrite, null, 2)], { type: "text/json" });
const link = document.createElement("a");