mirror of
https://github.com/RoboSats/robosats.git
synced 2024-12-13 10:56:24 +00:00
Add tooltips and helper buttons
This commit is contained in:
parent
d492475eec
commit
83564df25a
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user