Refactor avatars (#251)

This commit is contained in:
KoalaSat 2022-09-23 01:55:11 +02:00 committed by Reckless_Satoshi
parent c9a18751e9
commit ae193f19a4
No known key found for this signature in database
GPG Key ID: 9C4585B561315571
13 changed files with 171 additions and 230 deletions

View File

@ -46,10 +46,8 @@ jobs:
with:
images: recksato/robosats-client
tags: |
type=ref,event=branch
type=ref,event=pr
type=ref,event=tag
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,enable=true,priority=100,prefix=,suffix=,format=short
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
@ -71,5 +69,4 @@ jobs:
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
labels: ${{ steps.meta.outputs.labels }}

View File

@ -35,10 +35,8 @@ jobs:
with:
images: recksato/robosats
tags: |
type=ref,event=branch
type=ref,event=pr
type=ref,event=tag
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,enable=true,priority=100,prefix=,suffix=,format=short
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
@ -57,5 +55,4 @@ jobs:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
labels: ${{ steps.meta.outputs.labels }}

View File

@ -54,17 +54,16 @@ jobs:
name: main-js
path: frontend/static/frontend/main.js
invoke-docker-builds:
if: inputs.semver == ''
runs-on: ubuntu-latest
needs: build
steps:
# Invoke pre-release image build if this was not a tag push
# Docker images tagged only with short commit hash
- name: 'Invoke Coodinator Image CI'
if: inputs.semver == ''
uses: benc-uk/workflow-dispatch@v1
with:
workflow: 'Coodinator Image CI'
token: ${{ secrets.PERSONAL_TOKEN }}
- name: 'Invoke Client App Build CI/CD workflow'
if: inputs.semver == ''
uses: benc-uk/workflow-dispatch@v1
with:
workflow: 'Client App Image CI/CD'

View File

@ -96,6 +96,4 @@ jobs:
# upload_url: ${{ steps.create-release.outputs.upload_url }}
# asset_path: app-release.apk
# asset_name: robosats-${{ needs.check-versions.outputs.semver }}.apk
# asset_content_type: application/apk
# asset_content_type: application/apk

View File

@ -81,13 +81,13 @@ class BookPage extends Component {
// Colors for the status badges
statusBadgeColor(status) {
if (status == 'Active') {
if (status === 'Active') {
return 'success';
}
if (status == 'Seen recently') {
if (status === 'Seen recently') {
return 'warning';
}
if (status == 'Inactive') {
if (status === 'Inactive') {
return 'error';
}
}
@ -167,7 +167,12 @@ class BookPage extends Component {
return (
<ListItemButton style={{ cursor: 'pointer' }}>
<ListItemAvatar>
<RobotAvatar order={params.row} />
<RobotAvatar
nickname={params.row.maker_nick}
orderType={params.row.type}
statusColor={this.statusBadgeColor(params.row.maker_status)}
tooltip={t(params.row.maker_status)}
/>
</ListItemAvatar>
<ListItemText primary={params.row.maker_nick} />
</ListItemButton>
@ -307,7 +312,13 @@ class BookPage extends Component {
renderCell: (params) => {
return (
<div style={{ position: 'relative', left: '-5px' }}>
<RobotAvatar order={params.row} />
<RobotAvatar
nickname={params.row.maker_nick}
smooth={true}
orderType={params.row.type}
statusColor={this.statusBadgeColor(params.row.maker_status)}
tooltip={t(params.row.maker_status)}
/>
</div>
);
},

View File

@ -19,6 +19,7 @@ import MediaQuery from 'react-responsive';
import Flags from 'country-flag-icons/react/3x2';
import { Link as LinkRouter } from 'react-router-dom';
import { apiClient } from '../services/api';
import RobotAvatar from './Robots/RobotAvatar';
// Icons
import BarChartIcon from '@mui/icons-material/BarChart';
@ -204,29 +205,16 @@ class BottomBar extends Component {
}
>
<ListItemAvatar sx={{ width: 30 * fontSizeFactor, height: 30 * fontSizeFactor }}>
<Badge
badgeContent={
(this.props.activeOrderId > 0) & !this.props.profileShown ? '' : null
<RobotAvatar
style={{ marginTop: -13 }}
statusColor={
(this.props.activeOrderId > 0) & !this.props.profileShown
? 'primary'
: undefined
}
color='primary'
>
<Avatar
className='flippedSmallAvatar'
sx={{ margin: 0, top: -13 }}
alt={this.props.nickname}
imgProps={{
onLoad: () => this.props.setAppState({ avatarLoaded: true }),
}}
src={
this.props.nickname
? window.location.origin +
'/static/assets/avatars/' +
this.props.nickname +
'.png'
: null
}
/>
</Badge>
nickname={this.props.nickname}
onLoad={() => this.props.setAppState({ avatarLoaded: true })}
/>
</ListItemAvatar>
</Tooltip>
<ListItemText primary={this.props.nickname} />
@ -512,29 +500,17 @@ class BottomBar extends Component {
onClick={this.handleClickOpenProfile}
sx={{ margin: 0, bottom: 17, right: 8 }}
>
<Badge
badgeContent={
(this.state.active_order_id > 0) & !this.state.profileShown ? '' : null
<RobotAvatar
style={{ width: 55, height: 55 }}
avatarClass='phoneFlippedSmallAvatar'
statusColor={
(this.props.activeOrderId > 0) & !this.props.profileShown
? 'primary'
: undefined
}
color='primary'
>
<Avatar
className='phoneFlippedSmallAvatar'
sx={{ width: 55, height: 55 }}
alt={this.props.nickname}
imgProps={{
onLoad: () => this.props.setAppState({ avatarLoaded: true }),
}}
src={
this.props.nickname
? window.location.origin +
'/static/assets/avatars/' +
this.props.nickname +
'.png'
: null
}
/>
</Badge>
nickname={this.props.nickname}
onLoad={() => this.props.setAppState({ avatarLoaded: true })}
/>
</IconButton>
</Tooltip>
</div>

View File

@ -216,6 +216,17 @@ const DepthChart: React.FC<DepthChartProps> = ({
/>
);
const statusBadgeColor = (status: string) => {
if (status === 'Active') {
return 'success';
}
if (status === 'Seen recently') {
return 'warning';
}
return 'error';
};
const generateTooltip: React.FunctionComponent<PointTooltipProps> = (
pointTooltip: PointTooltipProps,
) => {
@ -225,7 +236,12 @@ const DepthChart: React.FC<DepthChartProps> = ({
<Grid container justifyContent='space-between'>
<Grid item xs={3}>
<Grid container justifyContent='center' alignItems='center'>
<RobotAvatar order={order} />
<RobotAvatar
nickname={order.maker_nick}
orderType={order.type}
statusColor={statusBadgeColor(order.maker_status)}
tooltip={t(order.maker_status)}
/>
</Grid>
</Grid>
<Grid item xs={8}>

View File

@ -39,6 +39,7 @@ import { UserNinjaIcon, BitcoinIcon } from '../Icons';
import { getCookie } from '../../utils/cookies';
import { copyToClipboard } from '../../utils/clipboard';
import { getWebln } from '../../utils/webln';
import RobotAvatar from '../Robots/RobotAvatar';
interface Props {
isOpen: boolean;
@ -167,13 +168,10 @@ const ProfileDialog = ({
</ListItemText>
<ListItemAvatar>
<Avatar
className='profileAvatar'
sx={{ width: 65, height: 65 }}
alt={nickname}
src={
nickname ? `${window.location.origin}/static/assets/avatars/${nickname}.png` : ''
}
<RobotAvatar
avatarClass='profileAvatar'
style={{ width: 65, height: 65 }}
nickname={nickname}
/>
</ListItemAvatar>
</ListItem>

View File

@ -20,6 +20,7 @@ import { getCookie } from '../utils/cookies';
import { saveAsJson } from '../utils/saveFile';
import { copyToClipboard } from '../utils/clipboard';
import { AuditPGPDialog } from './Dialogs';
import RobotAvatar from './Robots/RobotAvatar';
// Icons
import CheckIcon from '@mui/icons-material/Check';
@ -270,23 +271,10 @@ class Chat extends Component {
<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>
<RobotAvatar
statusColor={props.userConnected ? 'success' : 'error'}
nickname={props.message.userNick}
/>
}
style={{ backgroundColor: props.cardColor }}
title={

View File

@ -55,6 +55,7 @@ import { pn } from '../utils/prettyNumbers';
import { copyToClipboard } from '../utils/clipboard';
import { getWebln } from '../utils/webln';
import { apiClient } from '../services/api';
import RobotAvatar from './Robots/RobotAvatar';
class OrderPage extends Component {
constructor(props) {
@ -667,13 +668,13 @@ class OrderPage extends Component {
// Colors for the status badges
statusBadgeColor(status) {
if (status == 'Active') {
if (status === 'Active') {
return 'success';
}
if (status == 'Seen recently') {
if (status === 'Seen recently') {
return 'warning';
}
if (status == 'Inactive') {
if (status === 'Inactive') {
return 'error';
}
}
@ -692,46 +693,12 @@ class OrderPage extends Component {
<List dense={true}>
<ListItem>
<ListItemAvatar sx={{ width: 56, height: 56 }}>
<Tooltip placement='top' enterTouchDelay={0} title={t(this.state.maker_status)}>
<Badge
variant='dot'
overlap='circular'
badgeContent=''
color={this.statusBadgeColor(this.state.maker_status)}
>
<Badge
overlap='circular'
anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }}
badgeContent={
<div style={{ position: 'relative', left: '5px', top: '2px' }}>
{' '}
{!this.state.type ? (
<SendReceiveIcon
sx={{ transform: 'scaleX(-1)', height: '18px', width: '18px' }}
color='secondary'
/>
) : (
<SendReceiveIcon
sx={{ height: '18px', width: '18px' }}
color='primary'
/>
)}
</div>
}
>
<Avatar
className='flippedSmallAvatar'
alt={this.state.maker_nick}
src={
window.location.origin +
'/static/assets/avatars/' +
this.state.maker_nick +
'.png'
}
/>
</Badge>
</Badge>
</Tooltip>
<RobotAvatar
statusColor={this.statusBadgeColor(this.state.maker_status)}
nickname={this.state.maker_nick}
tooltip={t(this.state.maker_status)}
orderType={this.state.type}
/>
</ListItemAvatar>
<ListItemText
primary={
@ -745,7 +712,7 @@ class OrderPage extends Component {
{this.state.is_participant ? (
<>
{this.state.taker_nick != 'None' ? (
{this.state.taker_nick !== 'None' ? (
<>
<Divider />
<ListItem align='left'>
@ -757,50 +724,13 @@ class OrderPage extends Component {
secondary={t('Order taker')}
/>
<ListItemAvatar>
<Tooltip enterTouchDelay={0} title={t(this.state.taker_status)}>
<Badge
variant='dot'
overlap='circular'
badgeContent=''
color={this.statusBadgeColor(this.state.taker_status)}
>
<Badge
overlap='circular'
anchorOrigin={{ horizontal: 'left', vertical: 'bottom' }}
badgeContent={
<div style={{ position: 'relative', right: '5px', top: '2px' }}>
{' '}
{this.state.type ? (
<SendReceiveIcon
sx={{ height: '18px', width: '18px' }}
color='secondary'
/>
) : (
<SendReceiveIcon
sx={{
transform: 'scaleX(-1)',
height: '18px',
width: '18px',
}}
color='primary'
/>
)}
</div>
}
>
<Avatar
className='smallAvatar'
alt={this.state.taker_nick}
src={
window.location.origin +
'/static/assets/avatars/' +
this.state.taker_nick +
'.png'
}
/>
</Badge>
</Badge>
</Tooltip>
<RobotAvatar
avatarClass='smallAvatar'
statusColor={this.statusBadgeColor(this.state.taker_status)}
nickname={this.state.taker_nick}
tooltip={t(this.state.taker_status)}
orderType={this.state.type === 0 ? 1 : 0}
/>
</ListItemAvatar>
</ListItem>
</>

View File

@ -1,24 +1,37 @@
import React from 'react';
import { Badge, Tooltip } from '@mui/material';
import SmoothImage from 'react-smooth-image';
import Order from '../../../models/Order.model';
import { Avatar, Badge, Tooltip } from '@mui/material';
import { useTranslation } from 'react-i18next';
import { SendReceiveIcon } from '../../Icons';
interface DepthChartProps {
order: Order;
nickname: string;
smooth?: boolean;
style?: object;
statusColor?: 'primary' | 'secondary' | 'default' | 'error' | 'info' | 'success' | 'warning';
orderType?: number;
tooltip?: string;
avatarClass?: string;
onLoad?: () => void;
}
const RobotAvatar: React.FC<DepthChartProps> = ({ order }) => {
const RobotAvatar: React.FC<DepthChartProps> = ({
nickname,
orderType,
statusColor,
tooltip,
smooth = false,
style = {},
avatarClass = 'flippedSmallAvatar',
onLoad = () => {},
}) => {
const { t } = useTranslation();
const avatarSrc: string =
window.location.origin + '/static/assets/avatars/' + order?.maker_nick + '.png';
const avatarSrc: string = window.location.origin + '/static/assets/avatars/' + nickname + '.png';
const statusBadge = (
<div style={{ position: 'relative', left: '6px', top: '1px' }}>
{order?.type === 0 ? (
{orderType === 0 ? (
<SendReceiveIcon
sx={{ transform: 'scaleX(-1)', height: '18px', width: '18px' }}
color='secondary'
@ -29,45 +42,68 @@ const RobotAvatar: React.FC<DepthChartProps> = ({ order }) => {
</div>
);
const statusBadgeColor = () => {
if (!order) {
return;
}
if (order.maker_status === 'Active') {
return 'success';
}
if (order.maker_status === 'Seen recently') {
return 'warning';
}
if (order.maker_status === 'Inactive') {
return 'error';
const getAvatar = () => {
if (smooth) {
return (
<SmoothImage
className={avatarClass}
src={avatarSrc}
imageStyles={{
...style,
borderRadius: '50%',
transform: 'scaleX(-1)',
border: '0.3px solid #555',
filter: 'dropShadow(0.5px 0.5px 0.5px #000000)',
}}
/>
);
} else {
return (
<Avatar
className={avatarClass}
style={style}
alt={nickname}
src={avatarSrc}
imgProps={{
onLoad,
}}
/>
);
}
};
return order ? (
<Tooltip placement='right' enterTouchDelay={0} title={t(order.maker_status) || ''}>
<Badge variant='dot' overlap='circular' badgeContent='' color={statusBadgeColor()}>
const getAvatarWithBadges = () => {
let component = getAvatar();
if (statusColor) {
component = (
<Badge variant='dot' overlap='circular' badgeContent='' color={statusColor}>
{component}
</Badge>
);
}
if (orderType !== undefined) {
component = (
<Badge
overlap='circular'
anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }}
badgeContent={statusBadge}
>
<div style={{ width: 45, height: 45 }}>
<SmoothImage
src={avatarSrc}
imageStyles={{
borderRadius: '50%',
transform: 'scaleX(-1)',
border: '0.3px solid #555',
filter: 'dropShadow(0.5px 0.5px 0.5px #000000)',
}}
/>
</div>
{component}
</Badge>
</Badge>
);
}
return component;
};
return tooltip ? (
<Tooltip placement='right' enterTouchDelay={0} title={tooltip}>
{getAvatarWithBadges()}
</Tooltip>
) : (
<></>
getAvatarWithBadges()
);
};

View File

@ -20,6 +20,7 @@ import {
} from '@mui/material';
import { pn } from '../utils/prettyNumbers';
import { saveAsJson } from '../utils/saveFile';
import RobotAvatar from './Robots/RobotAvatar';
// Icons
import FlagWithProps from './FlagWithProps';
@ -94,12 +95,7 @@ const TradeSummary = ({
>
<ToggleButtonGroup size='small' value={buttonValue} exclusive>
<ToggleButton value={0} disableRipple={true} onClick={() => setButtonValue(0)}>
<Avatar
className='flippedSmallAvatar'
sx={{ height: 24, width: 24 }}
alt={makerNick}
src={window.location.origin + '/static/assets/avatars/' + makerNick + '.png'}
/>
<RobotAvatar style={{ height: 24, width: 24 }} nickname={makerNick} />
&nbsp;
{t('Maker')}
</ToggleButton>
@ -109,11 +105,10 @@ const TradeSummary = ({
<ToggleButton value={2} disableRipple={true} onClick={() => setButtonValue(2)}>
{t('Taker')}
&nbsp;
<Avatar
className='smallAvatar'
sx={{ height: 28, width: 28 }}
alt={takerNick}
src={window.location.origin + '/static/assets/avatars/' + takerNick + '.png'}
<RobotAvatar
avatarClass='smallAvatar'
style={{ height: 28, width: 28 }}
nickname={takerNick}
/>
</ToggleButton>
</ToggleButtonGroup>

View File

@ -6,7 +6,7 @@
"Hide": "Amagar",
"You are self-hosting RoboSats": "Estàs hostejant RoboSats",
"RoboSats client is served from your own node granting you the strongest security and privacy.": "El client RoboSats és servit pel teu propi node, gaudeixes de la major seguretat i privacitat.",
"USER GENERATION PAGE - UserGenPage.js": "Landing Page and User Generation",
"Simple and Private LN P2P Exchange": "Intercanvi LN P2P Fàcil y Privat",
"This is your trading avatar": "Aquest és el teu Robot de compravenda",
@ -88,7 +88,7 @@
"Google Play Gift Code": "Targeta Regal de Google Play",
"Cash F2F": "Efectiu en persona",
"On-Chain BTC": "On-Chain BTC",
"BOOK PAGE - BookPage.js": "The Book Order page",
"Seller": "Ven",
"Buyer": "Compra",
@ -235,7 +235,7 @@
"On your own sovereign node": "Al teu propi node sobirà",
"Simply refresh your Tor Browser tab (or press Ctrl+Shift+R)": "Simplement actualitzeu la pestanya del navegador Tor (o premeu Ctrl+Shift+R)",
"On remotely served client via web": "Al client servit de forma remota via web",
"ORDER PAGE - OrderPage.js": "Order details page",
"Order Box": "Ordre",
"Contract": "Contracte",
@ -310,7 +310,7 @@
"Payment not received, please check your WebLN wallet.": "No s'ha rebut el pagament, fes un cop d'ull a la teva wallet WebLN.",
"Invoice not received, please check your WebLN wallet.": "No s'ha rebut la factura, fes un cop d'ull a la teva wallet WebLN.",
"You can close now your WebLN wallet popup.": "Ara pots tancar el popup de la teva wallet WebLN.",
"CHAT BOX - Chat.js": "Finestra del xat",
"You": "Tu",
"Peer": "Ell",
@ -446,7 +446,7 @@
"The invoice provided has already expired": "La factura que has entregat ja ha caducat",
"Make sure to EXPORT the chat log. The staff might request your exported chat log JSON in order to solve discrepancies. It is your responsibility to store it.": "Assegura't d' EXPORTAR el registre del xat. Els administradors poden demanar-te elregistre del xat en cas de discrepàncies. És la teva responsabilitat proveir-ho.",
"Invalid address": "Direcció invàlida",
"Unable to validate address, check bitcoind backend": "No ha estat possible validar l'adreça, comprovar el backend bitcoind",
"Unable to validate address, check bitcoind backend": "No ha estat possible validar l'adreça, comprovar el backend bitcoind",
"Submit payout info for {{amountSats}} Sats": "Envia info per rebre {{amountSats}} Sats",
"Submit a valid invoice for {{amountSats}} Satoshis.": "Envia una factura per {{amountSats}} Sats",
"Before letting you send {{amountFiat}} {{currencyCode}}, we want to make sure you are able to receive the BTC.": "Abans de deixar-te enviar {{amountFiat}} {{currencyCode}}, volem assegurar-nos que pots rebre BTC.",