Add showPGP per message, copy per message, create messageCard

This commit is contained in:
Reckless_Satoshi 2022-05-24 14:36:21 -07:00
parent 83564df25a
commit 508151eae5
No known key found for this signature in database
GPG Key ID: 9C4585B561315571
4 changed files with 171 additions and 73 deletions

View File

@ -110,7 +110,6 @@ class ChatRoomConsumer(AsyncWebsocketConsumer):
async def receive(self, text_data):
text_data_json = json.loads(text_data)
print(text_data)
message = text_data_json["message"]
peer_connected = await self.is_peer_connected()

View File

@ -20,7 +20,7 @@ import { saveAsJson } from "../../utils/saveFile";
import KeyIcon from '@mui/icons-material/Key';
import ContentCopy from "@mui/icons-material/ContentCopy";
import ForumIcon from '@mui/icons-material/Forum';
import { ExportIcon } from '../Icons';
import { ExportIcon, NewTabIcon } from '../Icons';
type Props = {
open: boolean;
@ -53,7 +53,7 @@ const AuditPGPDialog = ({
onClose={onClose}
>
<DialogTitle >
{t("Do not trust, verify!")}
{t("Don't trust, verify")}
</DialogTitle>
<DialogContent>
@ -63,7 +63,7 @@ const AuditPGPDialog = ({
<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 verify")}</Button>
<Button component={Link} target="_blank" href="https://learn.robosats.com/docs/pgp-encryption">{t("Learn how to verify")} <NewTabIcon sx={{width:16,height:16}}/></Button>
</Grid>
<Grid item align="center" xs={12}>

View File

@ -12,6 +12,7 @@ import CheckIcon from '@mui/icons-material/Check';
import CloseIcon from '@mui/icons-material/Close';
import ContentCopy from "@mui/icons-material/ContentCopy";
import VisibilityIcon from '@mui/icons-material/Visibility';
import CircularProgress from '@mui/material/CircularProgress';
import KeyIcon from '@mui/icons-material/Key';
import { ExportIcon } from './Icons';
@ -30,10 +31,13 @@ class Chat extends Component {
connected: false,
peer_connected: false,
audit: false,
showPGP: new Array,
waitingEcho: false,
lastSent: '---BLANK---',
};
rws = new ReconnectingWebSocket('ws://' + window.location.host + '/ws/chat/' + this.props.orderId + '/');
componentDidMount() {
this.rws.addEventListener('open', () => {
console.log('Connected!');
@ -93,6 +97,8 @@ class Chat extends Component {
.then((decryptedData) =>
this.setState((state) =>
({
waitingEcho: this.state.waitingEcho == true ? (decryptedData.decryptedMessage == this.state.lastSent ? false: true ) : false,
lastSent: decryptedData.decryptedMessage == this.state.lastSent ? '----BLANK----': this.state.lastSent,
messages: [...state.messages,
{
encryptedMessage: dataFromServer.message.split('\\').join('\n'),
@ -129,6 +135,7 @@ class Chat extends Component {
onButtonClicked = (e) => {
if(this.state.value!=''){
this.setState({waitingEcho:true, lastSent:this.state.value});
encryptMessage(this.state.value, this.state.own_pub_key, this.state.peer_pub_key, this.state.own_enc_priv_key, this.state.token)
.then((encryptedMessage) =>
console.log("Sending Encrypted MESSAGE "+encryptedMessage) &
@ -137,7 +144,7 @@ class Chat extends Component {
message: encryptedMessage.split('\n').join('\\'),
nick: this.props.ur_nick,
})
) & this.setState({value: ""})
) & this.setState({value: "", waitingEcho: false})
);
}
e.preventDefault();
@ -154,6 +161,60 @@ class Chat extends Component {
})
}
messageCard = (props) => {
const { t } = this.props;
return(
<Card elevation={5} align="left" >
<CardHeader sx={{color: '#333333'}}
avatar={
<Badge variant="dot" overlap="circular" badgeContent="" color={props.userConnected ? "success" : "error"}>
<Avatar className="flippedSmallAvatar"
alt={props.message.userNick}
src={window.location.origin +'/static/assets/avatars/' + props.message.userNick + '.png'}
/>
</Badge>
}
style={{backgroundColor: props.cardColor}}
title={
<Tooltip placement="top" enterTouchDelay={0} enterDelay={500} enterNextDelay={2000} title={t(props.message.validSignature ? "Verified signature by {{nickname}}": "Invalid signature! Not sent by {{nickname}}",{"nickname": props.message.userNick})}>
<div style={{display:'flex',alignItems:'center', flexWrap:'wrap', position:'relative',left:-5, width:210}}>
<div style={{width:168,display:'flex',alignItems:'center', flexWrap:'wrap'}}>
{props.message.userNick}
{props.message.validSignature ?
<CheckIcon sx={{height:16}} color="success"/>
:
<CloseIcon sx={{height:16}} color="error"/>
}
</div>
<div style={{width:20}}>
<IconButton sx={{height:18,width:18}}
onClick={()=>
this.setState(prevState => {
const newShowPGP = [...prevState.showPGP];
newShowPGP[props.index] = !newShowPGP[props.index];
return {showPGP: newShowPGP};
})}>
<VisibilityIcon color={this.state.showPGP[props.index]? "primary":"inherit"} sx={{height:16,width:16,color:this.state.showPGP[props.index]? "primary":"#333333"}}/>
</IconButton>
</div>
<div style={{width:20}}>
<Tooltip disableHoverListener enterTouchDelay={0} title={t("Copied!")}>
<IconButton sx={{height:18,width:18}}
onClick={()=> navigator.clipboard.writeText(this.state.showPGP[props.index] ? props.message.encryptedMessage : props.message.plainTextMessage)}>
<ContentCopy sx={{height:16,width:16,color:'#333333'}}/>
</IconButton>
</Tooltip>
</div>
</div>
</Tooltip>
}
subheader={this.state.showPGP[props.index] ? props.message.encryptedMessage : props.message.plainTextMessage}
subheaderTypographyProps={{sx: {wordWrap: "break-word", width: '200px', color: '#444444', fontSize: this.state.showPGP[props.index]? 11 : null }}}
/>
</Card>
)
}
render() {
const { t } = this.props;
return (
@ -162,7 +223,7 @@ class Chat extends Component {
<Grid item xs={0.3}/>
<Grid item xs={5.5}>
<Paper elevation={1} style={this.state.connected ? {backgroundColor: '#e8ffe6'}: {backgroundColor: '#FFF1C5'}}>
<Typography variant='caption' sx={{color: '#111111'}}>
<Typography variant='caption' sx={{color: '#333333'}}>
{t("You")+": "}{this.state.connected ? t("connected"): t("disconnected")}
</Typography>
</Paper>
@ -170,7 +231,7 @@ class Chat extends Component {
<Grid item xs={0.4}/>
<Grid item xs={5.5}>
<Paper elevation={1} style={this.state.peer_connected ? {backgroundColor: '#e8ffe6'}: {backgroundColor: '#FFF1C5'}}>
<Typography variant='caption' sx={{color: '#111111'}}>
<Typography variant='caption' sx={{color: '#333333'}}>
{t("Peer")+": "}{this.state.peer_connected ? t("connected"): t("disconnected")}
</Typography>
</Paper>
@ -180,72 +241,101 @@ class Chat extends Component {
<Paper elevation={1} style={{ height: '300px', maxHeight: '300px' , width: '280px' ,overflow: 'auto', backgroundColor: '#F7F7F7' }}>
{this.state.messages.map((message, index) =>
<li style={{listStyleType:"none"}} key={index}>
<Card elevation={5} align="left" >
{/* If message sender is not our nick, gray color, if it is our nick, green color */}
{message.userNick == this.props.ur_nick ?
<CardHeader sx={{color: '#111111'}}
avatar={
<Badge variant="dot" overlap="circular" badgeContent="" color={this.state.connected ? "success" : "error"}>
<Avatar className="flippedSmallAvatar"
alt={message.userNick}
src={window.location.origin +'/static/assets/avatars/' + message.userNick + '.png'}
/>
</Badge>
}
style={{backgroundColor: '#eeeeee'}}
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'}}}
/>
<this.messageCard message={message} index={index} cardColor={'#eeeeee'} userConnected={this.state.connected}/>
:
<CardHeader sx={{color: '#111111'}}
avatar={
<Badge variant="dot" overlap="circular" badgeContent="" color={this.state.peer_connected ? "success" : "error"}>
<Avatar className="flippedSmallAvatar"
alt={message.userNick}
src={window.location.origin +'/static/assets/avatars/' + message.userNick + '.png'}
/>
</Badge>
}
style={{backgroundColor: '#fafafa'}}
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'}}}
/>}
</Card>
<this.messageCard message={message} index={index} cardColor={'#fafafa'} userConnected={this.state.peer_connected}/>
}
{/* // <CardHeader sx={{color: '#333333'}}
// avatar={
// <Badge variant="dot" overlap="circular" badgeContent="" color={this.state.connected ? "success" : "error"}>
// <Avatar className="flippedSmallAvatar"
// alt={message.userNick}
// src={window.location.origin +'/static/assets/avatars/' + message.userNick + '.png'}
// />
// </Badge>
// }
// style={{backgroundColor: '#eeeeee'}}
// 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', position:'relative',left:-5, width:210}}>
// <div style={{width:168,display:'flex',alignItems:'center', flexWrap:'wrap'}}>
// {message.userNick}
// {message.validSignature ?
// <CheckIcon sx={{height:16}} color="success"/>
// :
// <CloseIcon sx={{height:16}} color="error"/>
// }
// </div>
// <div style={{width:20}}>
// <IconButton sx={{height:18,width:18}}
// onClick={()=>
// this.setState(prevState => {
// const newShowPGP = [...prevState.showPGP];
// newShowPGP[index] = !newShowPGP[index];
// return {showPGP: newShowPGP};
// })}>
// <VisibilityIcon color={this.state.showPGP[index]? "primary":"inherit"} sx={{height:16,width:16,color:this.state.showPGP[index]? "primary":"#333333"}}/>
// </IconButton>
// </div>
// <div style={{width:20}}>
// <Tooltip disableHoverListener enterTouchDelay={0} title={t("Copied!")}>
// <IconButton sx={{height:18,width:18}}
// onClick={()=> navigator.clipboard.writeText(this.state.showPGP[index] ? message.encryptedMessage : message.plainTextMessage)}>
// <ContentCopy sx={{height:16,width:16,color:'#333333'}}/>
// </IconButton>
// </Tooltip>
// </div>
// </div>
// </Tooltip>
// }
// subheader={this.state.showPGP[index] ? message.encryptedMessage : message.plainTextMessage}
// subheaderTypographyProps={{sx: {wordWrap: "break-word", width: '200px', color: '#444444', fontSize: this.state.showPGP[index]? 11 : null }}}
// />
// :
// <CardHeader sx={{color: '#333333'}}
// avatar={
// <Badge variant="dot" overlap="circular" badgeContent="" color={this.state.peer_connected ? "success" : "error"}>
// <Avatar className="flippedSmallAvatar"
// alt={message.userNick}
// src={window.location.origin +'/static/assets/avatars/' + message.userNick + '.png'}
// />
// </Badge>
// }
// style={{backgroundColor: '#fafafa'}}
// 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', position:'relative',left:-5, width:210}}>
// <div style={{width:168,display:'flex',alignItems:'center', flexWrap:'wrap'}}>
// {message.userNick}
// {message.validSignature ?
// <CheckIcon sx={{height:16}} color="success"/>
// :
// <CloseIcon sx={{height:16}} color="error"/>
// }
// </div>
// <div style={{width:20}}>
// <IconButton sx={{height:18,width:18}}
// onClick={()=>
// this.setState(prevState => {
// const newShowPGP = [...prevState.showPGP];
// newShowPGP[index] = !newShowPGP[index];
// return {showPGP: newShowPGP};
// })}>
// <VisibilityIcon color={this.state.showPGP[index]? "primary":"inherit"} sx={{height:16,width:16,color:this.state.showPGP[index]? "primary":"#333333"}}/>
// </IconButton>
// </div>
// <div style={{width:20}}>
// <Tooltip disableHoverListener enterTouchDelay={0} title={t("Copied!")}>
// <IconButton sx={{height:18,width:18}}
// onClick={()=> navigator.clipboard.writeText(this.state.showPGP[index] ? message.encryptedMessage : message.plainTextMessage)}>
// <ContentCopy sx={{height:16,width:16,color:'#333333'}}/>
// </IconButton>
// </Tooltip>
// </div>
// </div>
// </Tooltip> */}
</li>)}
<div style={{ float:"left", clear: "both" }} ref={(el) => { this.messagesEnd = el; }}></div>
</Paper>
@ -266,7 +356,16 @@ class Chat extends Component {
/>
</Grid>
<Grid item alignItems="stretch" style={{ display: "flex" }}>
<Button sx={{'width':68}} disabled={!this.state.connected} type="submit" variant="contained" color="primary">{t("Send")} </Button>
<Button sx={{'width':68}} disabled={!this.state.connected || this.state.waitingEcho} type="submit" variant="contained" color="primary">
{this.state.waitingEcho ?
<div style={{display:'flex',alignItems:'center', flexWrap:'wrap', minWidth:68, width:68, position:"relative",left:15}}>
<div style={{width:20}}><KeyIcon sx={{width:18}}/></div>
<div style={{width:18}}><CircularProgress size={16} thickness={5}/></div>
</div>
:
t("Send")
}
</Button>
</Grid>
</Grid>
</form>

View File

@ -381,7 +381,7 @@
"You can also check the full guide in ":"You can also check the full guide in ",
"How to use":"How to use",
"What payment methods are accepted?":"What payment methods are accepted?",
"All of them as long as they are fast. You can write down your preferred payment method(s). You will have to match with a peer who also accepts that method. The step to exchange fiat has a expiry time of 24 hours before a dispute is automatically open. We highly recommend using instant fiat payment rails.":"All of them as long as they are fast. You can write down your preferred payment method(s). You will have to match with a peer who also accepts that method. The step to exchange fiat has a expiry time of 24 hours before a dispute is automatically open. We highly recommend using instant fiat payment rails.",
"All of them as long as they are fast. You can write down your preferred payment method(s). You will have to match with a peer who also accepts that method. The step to exchange fiat has a expiry time of 24 hours before a dispute is automatically open. We highly recommend using instant fiat payment rails.":"All of them as long as they are fast. You can write down your preferred payment method(s). You will have to match with a peer who also accepts that method. The step to exchange fiat has an expiry time of 24 hours before a dispute is automatically open. We highly recommend using instant fiat payment rails.",
"Are there trade limits?":"Are there trade limits?",
"Maximum single trade size is {{maxAmount}} Satoshis to minimize lightning routing failure. There is no limits to the number of trades per day. A robot can only have one order at a time. However, you can use multiple robots simultaneously in different browsers (remember to back up your robot tokens!).":"Maximum single trade size is {{maxAmount}} Satoshis to minimize lightning routing failure. There is no limits to the number of trades per day. A robot can only have one order at a time. However, you can use multiple robots simultaneously in different browsers (remember to back up your robot tokens!).",
"Is RoboSats private?":"Is RoboSats private?",