6th iteration: remove unused components

This commit is contained in:
Victor Baranov 2019-09-03 19:51:36 +03:00
parent 0749dc36ba
commit 5b5ec4585d
63 changed files with 0 additions and 5420 deletions

View File

@ -1,188 +0,0 @@
const Component = require('react').Component
const PropTypes = require('prop-types')
const h = require('react-hyperscript')
const inherits = require('util').inherits
const ethUtil = require('ethereumjs-util')
const BN = ethUtil.BN
const extend = require('xtend')
const connect = require('react-redux').connect
BnAsDecimalInput.contextTypes = {
t: PropTypes.func,
}
module.exports = connect()(BnAsDecimalInput)
inherits(BnAsDecimalInput, Component)
function BnAsDecimalInput () {
this.state = { invalid: null }
Component.call(this)
}
/* Bn as Decimal Input
*
* A component for allowing easy, decimal editing
* of a passed in bn string value.
*
* On change, calls back its `onChange` function parameter
* and passes it an updated bn string.
*/
BnAsDecimalInput.prototype.render = function () {
const props = this.props
const state = this.state
const { value, scale, precision, onChange, min, max } = props
const suffix = props.suffix
const style = props.style
const valueString = value.toString(10)
const newMin = min && this.downsize(min.toString(10), scale)
const newMax = max && this.downsize(max.toString(10), scale)
const newValue = this.downsize(valueString, scale)
return (
h('.flex-column', [
h('.flex-row', {
style: {
alignItems: 'flex-end',
lineHeight: '13px',
fontFamily: 'Montserrat Light',
textRendering: 'geometricPrecision',
},
}, [
h('input.hex-input', {
type: 'number',
step: 'any',
required: true,
min: newMin,
max: newMax,
style: extend({
display: 'block',
textAlign: 'right',
backgroundColor: 'transparent',
border: '1px solid #bdbdbd',
}, style),
value: newValue,
onBlur: (event) => {
this.updateValidity(event)
},
onChange: (event) => {
this.updateValidity(event)
const value = (event.target.value === '') ? '' : event.target.value
const scaledNumber = this.upsize(value, scale, precision)
const precisionBN = new BN(scaledNumber, 10)
onChange(precisionBN, event.target.checkValidity())
},
onInvalid: (event) => {
const msg = this.constructWarning()
if (msg === state.invalid) {
return
}
this.setState({ invalid: msg })
event.preventDefault()
return false
},
}),
h('div', {
style: {
color: ' #AEAEAE',
fontSize: '12px',
marginLeft: '5px',
marginRight: '6px',
width: '20px',
},
}, suffix),
]),
state.invalid ? h('span.error', {
style: {
position: 'absolute',
right: '0px',
textAlign: 'right',
transform: 'translateY(26px)',
padding: '3px',
background: 'rgba(255,255,255,0.85)',
zIndex: '1',
textTransform: 'capitalize',
border: '2px solid #E20202',
},
}, state.invalid) : null,
])
)
}
BnAsDecimalInput.prototype.setValid = function (message) {
this.setState({ invalid: null })
}
BnAsDecimalInput.prototype.updateValidity = function (event) {
const target = event.target
const value = this.props.value
const newValue = target.value
if (value === newValue) {
return
}
const valid = target.checkValidity()
if (valid) {
this.setState({ invalid: null })
}
}
BnAsDecimalInput.prototype.constructWarning = function () {
const { name, min, max, scale, suffix } = this.props
const newMin = min && this.downsize(min.toString(10), scale)
const newMax = max && this.downsize(max.toString(10), scale)
let message = name ? name + ' ' : ''
if (min && max) {
message += this.context.t('betweenMinAndMax', [`${newMin} ${suffix}`, `${newMax} ${suffix}`])
} else if (min) {
message += this.context.t('greaterThanMin', [`${newMin} ${suffix}`])
} else if (max) {
message += this.context.t('lessThanMax', [`${newMax} ${suffix}`])
} else {
message += this.context.t('invalidInput')
}
return message
}
BnAsDecimalInput.prototype.downsize = function (number, scale) {
// if there is no scaling, simply return the number
if (scale === 0) {
return Number(number)
} else {
// if the scale is the same as the precision, account for this edge case.
var adjustedNumber = number
while (adjustedNumber.length < scale) {
adjustedNumber = '0' + adjustedNumber
}
return Number(adjustedNumber.slice(0, -scale) + '.' + adjustedNumber.slice(-scale))
}
}
BnAsDecimalInput.prototype.upsize = function (number, scale, precision) {
var stringArray = number.toString().split('.')
var decimalLength = stringArray[1] ? stringArray[1].length : 0
var newString = stringArray[0]
// If there is scaling and decimal parts exist, integrate them in.
if ((scale !== 0) && (decimalLength !== 0)) {
newString += stringArray[1].slice(0, precision)
}
// Add 0s to account for the upscaling.
for (var i = decimalLength; i < scale; i++) {
newString += '0'
}
return newString
}

View File

@ -1,69 +0,0 @@
const Component = require('react').Component
const PropTypes = require('prop-types')
const h = require('react-hyperscript')
const inherits = require('util').inherits
const connect = require('react-redux').connect
const actions = require('../actions')
CoinbaseForm.contextTypes = {
t: PropTypes.func,
}
module.exports = connect(mapStateToProps)(CoinbaseForm)
function mapStateToProps (state) {
return {
warning: state.appState.warning,
}
}
inherits(CoinbaseForm, Component)
function CoinbaseForm () {
Component.call(this)
}
CoinbaseForm.prototype.render = function () {
var props = this.props
return h('.flex-column', {
style: {
marginTop: '35px',
padding: '25px',
width: '100%',
},
}, [
h('.flex-row', {
style: {
justifyContent: 'space-around',
margin: '33px',
marginTop: '0px',
},
}, [
h('button.btn-green', {
onClick: this.toCoinbase.bind(this),
}, this.context.t('continueToCoinbase')),
h('button.btn-red', {
onClick: () => props.dispatch(actions.goHome()),
}, this.context.t('cancel')),
]),
])
}
CoinbaseForm.prototype.toCoinbase = function () {
const props = this.props
const address = props.buyView.buyAddress
props.dispatch(actions.buyEth({ network: '1', address, amount: 0 }))
}
CoinbaseForm.prototype.renderLoading = function () {
return h('img', {
style: {
width: '27px',
marginRight: '-27px',
},
src: 'images/loading.svg',
})
}

View File

@ -1,88 +0,0 @@
const { Component } = require('react')
const PropTypes = require('prop-types')
const h = require('react-hyperscript')
const classnames = require('classnames')
class EditableLabel extends Component {
constructor (props) {
super(props)
this.state = {
isEditing: false,
value: props.defaultValue || '',
}
}
handleSubmit () {
const { value } = this.state
if (value === '') {
return
}
Promise.resolve(this.props.onSubmit(value))
.then(() => this.setState({ isEditing: false }))
}
saveIfEnter (event) {
if (event.key === 'Enter') {
this.handleSubmit()
}
}
renderEditing () {
const { value } = this.state
return ([
h('input.large-input.editable-label__input', {
type: 'text',
required: true,
value: this.state.value,
onKeyPress: (event) => {
if (event.key === 'Enter') {
this.handleSubmit()
}
},
onChange: event => this.setState({ value: event.target.value }),
className: classnames({ 'editable-label__input--error': value === '' }),
}),
h('div.editable-label__icon-wrapper', [
h('i.fa.fa-check.editable-label__icon', {
onClick: () => this.handleSubmit(),
}),
]),
])
}
renderReadonly () {
return ([
h('div.editable-label__value', this.state.value),
h('div.editable-label__icon-wrapper', [
h('i.fa.fa-pencil.editable-label__icon', {
onClick: () => this.setState({ isEditing: true }),
}),
]),
])
}
render () {
const { isEditing } = this.state
const { className } = this.props
return (
h('div.editable-label', { className: classnames(className) },
isEditing
? this.renderEditing()
: this.renderReadonly()
)
)
}
}
EditableLabel.propTypes = {
onSubmit: PropTypes.func.isRequired,
defaultValue: PropTypes.string,
className: PropTypes.string,
}
module.exports = EditableLabel

View File

@ -1,181 +0,0 @@
const Component = require('react').Component
const PropTypes = require('prop-types')
const h = require('react-hyperscript')
const inherits = require('util').inherits
const extend = require('xtend')
const debounce = require('debounce')
const copyToClipboard = require('copy-to-clipboard')
const ENS = require('ethjs-ens')
const networkMap = require('ethjs-ens/lib/network-map.json')
const ensRE = /.+\..+$/
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
const connect = require('react-redux').connect
const ToAutoComplete = require('./send/to-autocomplete').default
const log = require('loglevel')
const { isValidENSAddress } = require('../util')
EnsInput.contextTypes = {
t: PropTypes.func,
}
module.exports = connect()(EnsInput)
inherits(EnsInput, Component)
function EnsInput () {
Component.call(this)
}
EnsInput.prototype.onChange = function (recipient) {
const network = this.props.network
const networkHasEnsSupport = getNetworkEnsSupport(network)
this.props.onChange({ toAddress: recipient })
if (!networkHasEnsSupport) return
if (recipient.match(ensRE) === null) {
return this.setState({
loadingEns: false,
ensResolution: null,
ensFailure: null,
toError: null,
})
}
this.setState({
loadingEns: true,
})
this.checkName(recipient)
}
EnsInput.prototype.render = function () {
const props = this.props
const opts = extend(props, {
list: 'addresses',
onChange: this.onChange.bind(this),
qrScanner: true,
})
return h('div', {
style: { width: '100%', position: 'relative' },
}, [
h(ToAutoComplete, { ...opts }),
this.ensIcon(),
])
}
EnsInput.prototype.componentDidMount = function () {
const network = this.props.network
const networkHasEnsSupport = getNetworkEnsSupport(network)
this.setState({ ensResolution: ZERO_ADDRESS })
if (networkHasEnsSupport) {
const provider = global.ethereumProvider
this.ens = new ENS({ provider, network })
this.checkName = debounce(this.lookupEnsName.bind(this), 200)
}
}
EnsInput.prototype.lookupEnsName = function (recipient) {
const { ensResolution } = this.state
log.info(`ENS attempting to resolve name: ${recipient}`)
this.ens.lookup(recipient.trim())
.then((address) => {
if (address === ZERO_ADDRESS) throw new Error(this.context.t('noAddressForName'))
if (address !== ensResolution) {
this.setState({
loadingEns: false,
ensResolution: address,
nickname: recipient.trim(),
hoverText: address + '\n' + this.context.t('clickCopy'),
ensFailure: false,
toError: null,
})
}
})
.catch((reason) => {
const setStateObj = {
loadingEns: false,
ensResolution: recipient,
ensFailure: true,
toError: null,
}
if (isValidENSAddress(recipient) && reason.message === 'ENS name not defined.') {
setStateObj.hoverText = this.context.t('ensNameNotFound')
setStateObj.toError = 'ensNameNotFound'
setStateObj.ensFailure = false
} else {
log.error(reason)
setStateObj.hoverText = reason.message
}
return this.setState(setStateObj)
})
}
EnsInput.prototype.componentDidUpdate = function (prevProps, prevState) {
const state = this.state || {}
const ensResolution = state.ensResolution
// If an address is sent without a nickname, meaning not from ENS or from
// the user's own accounts, a default of a one-space string is used.
const nickname = state.nickname || ' '
if (prevProps.network !== this.props.network) {
const provider = global.ethereumProvider
this.ens = new ENS({ provider, network: this.props.network })
this.onChange(ensResolution)
}
if (prevState && ensResolution && this.props.onChange &&
ensResolution !== prevState.ensResolution) {
this.props.onChange({ toAddress: ensResolution, nickname, toError: state.toError })
}
}
EnsInput.prototype.ensIcon = function (recipient) {
const { hoverText } = this.state || {}
return h('span.#ensIcon', {
title: hoverText,
style: {
position: 'absolute',
top: '16px',
left: '-25px',
},
}, this.ensIconContents(recipient))
}
EnsInput.prototype.ensIconContents = function (recipient) {
const { loadingEns, ensFailure, ensResolution, toError } = this.state || { ensResolution: ZERO_ADDRESS }
if (toError) return
if (loadingEns) {
return h('img', {
src: 'images/loading.svg',
style: {
width: '30px',
height: '30px',
transform: 'translateY(-6px)',
},
})
}
if (ensFailure) {
return h('i.fa.fa-warning.fa-lg.warning')
}
if (ensResolution && (ensResolution !== ZERO_ADDRESS)) {
return h('i.fa.fa-check-circle.fa-lg.cursor-pointer', {
style: { color: 'green' },
onClick: (event) => {
event.preventDefault()
event.stopPropagation()
copyToClipboard(ensResolution)
},
})
}
}
function getNetworkEnsSupport (network) {
return Boolean(networkMap[network])
}

View File

@ -1,96 +0,0 @@
const { Component } = require('react')
const h = require('react-hyperscript')
const { inherits } = require('util')
const {
formatBalance,
generateBalanceObject,
} = require('../util')
const Tooltip = require('./tooltip.js')
const FiatValue = require('./fiat-value.js')
module.exports = EthBalanceComponent
inherits(EthBalanceComponent, Component)
function EthBalanceComponent () {
Component.call(this)
}
EthBalanceComponent.prototype.render = function () {
const props = this.props
const { value, style, width, needsParse = true } = props
const formattedValue = value ? formatBalance(value, 6, needsParse) : '...'
return (
h('.ether-balance.ether-balance-amount', {
style,
}, [
h('div', {
style: {
display: 'inline',
width,
},
}, this.renderBalance(formattedValue)),
])
)
}
EthBalanceComponent.prototype.renderBalance = function (value) {
if (value === 'None') return value
if (value === '...') return value
const {
conversionRate,
shorten,
incoming,
currentCurrency,
hideTooltip,
styleOveride = {},
showFiat = true,
} = this.props
const { fontSize, color, fontFamily, lineHeight } = styleOveride
const { shortBalance, balance, label } = generateBalanceObject(value, shorten ? 1 : 3)
const balanceToRender = shorten ? shortBalance : balance
const [ethNumber, ethSuffix] = value.split(' ')
const containerProps = hideTooltip ? {} : {
position: 'bottom',
title: `${ethNumber} ${ethSuffix}`,
}
return (
h(hideTooltip ? 'div' : Tooltip,
containerProps,
h('div.flex-column', [
h('.flex-row', {
style: {
alignItems: 'flex-end',
lineHeight: lineHeight || '13px',
fontFamily: fontFamily || 'Montserrat Light',
textRendering: 'geometricPrecision',
},
}, [
h('div', {
style: {
width: '100%',
textAlign: 'right',
fontSize: fontSize || 'inherit',
color: color || 'inherit',
},
}, incoming ? `+${balanceToRender}` : balanceToRender),
h('div', {
style: {
color: color || '#AEAEAE',
fontSize: fontSize || '12px',
marginLeft: '5px',
},
}, label),
]),
showFiat ? h(FiatValue, { value: this.props.value, conversionRate, currentCurrency }) : null,
])
)
)
}

View File

@ -1,45 +0,0 @@
const { Component } = require('react')
const PropTypes = require('prop-types')
const h = require('react-hyperscript')
const copyToClipboard = require('copy-to-clipboard')
const { exportAsFile } = require('../../util')
class ExportTextContainer extends Component {
render () {
const { text = '', filename = '' } = this.props
const { t } = this.context
return (
h('.export-text-container', [
h('.export-text-container__text-container', [
h('.export-text-container__text', text),
]),
h('.export-text-container__buttons-container', [
h('.export-text-container__button.export-text-container__button--copy', {
onClick: () => copyToClipboard(text),
}, [
h('img', { src: 'images/copy-to-clipboard.svg' }),
h('.export-text-container__button-text', t('copyToClipboard')),
]),
h('.export-text-container__button', {
onClick: () => exportAsFile(filename, text),
}, [
h('img', { src: 'images/download.svg' }),
h('.export-text-container__button-text', t('saveAsCsvFile')),
]),
]),
])
)
}
}
ExportTextContainer.propTypes = {
text: PropTypes.string,
filename: PropTypes.string,
}
ExportTextContainer.contextTypes = {
t: PropTypes.func,
}
module.exports = ExportTextContainer

View File

@ -1,2 +0,0 @@
const ExportTextContainer = require('./export-text-container.component')
module.exports = ExportTextContainer

View File

@ -1,52 +0,0 @@
.export-text-container {
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
border: 1px solid $alto;
border-radius: 4px;
font-weight: 400;
&__text-container {
width: 100%;
display: flex;
justify-content: center;
padding: 20px;
border-radius: 4px;
background: $alabaster;
}
&__text {
resize: none;
border: none;
background: $alabaster;
font-size: 20px;
text-align: center;
}
&__buttons-container {
display: flex;
flex-direction: row;
border-top: 1px solid $alto;
width: 100%;
}
&__button {
padding: 10px;
flex: 1;
display: flex;
justify-content: center;
align-items: center;
font-size: 12px;
cursor: pointer;
color: $curious-blue;
&--copy {
border-right: 1px solid $alto;
}
}
&__button-text {
padding-left: 10px;
}
}

View File

@ -1,66 +0,0 @@
const Component = require('react').Component
const h = require('react-hyperscript')
const inherits = require('util').inherits
const formatBalance = require('../util').formatBalance
module.exports = FiatValue
inherits(FiatValue, Component)
function FiatValue () {
Component.call(this)
}
FiatValue.prototype.render = function () {
const props = this.props
const { conversionRate, currentCurrency, style } = props
const renderedCurrency = currentCurrency || ''
const value = formatBalance(props.value, 6)
if (value === 'None') return value
var fiatDisplayNumber, fiatTooltipNumber
var splitBalance = value.split(' ')
if (conversionRate !== 0) {
fiatTooltipNumber = Number(splitBalance[0]) * conversionRate
fiatDisplayNumber = fiatTooltipNumber.toFixed(2)
} else {
fiatDisplayNumber = 'N/A'
fiatTooltipNumber = 'Unknown'
}
return fiatDisplay(fiatDisplayNumber, renderedCurrency.toUpperCase(), style)
}
function fiatDisplay (fiatDisplayNumber, fiatSuffix, styleOveride = {}) {
const { fontSize, color, fontFamily, lineHeight } = styleOveride
if (fiatDisplayNumber !== 'N/A') {
return h('.flex-row', {
style: {
alignItems: 'flex-end',
lineHeight: lineHeight || '13px',
fontFamily: fontFamily || 'Montserrat Light',
textRendering: 'geometricPrecision',
},
}, [
h('div', {
style: {
width: '100%',
textAlign: 'right',
fontSize: fontSize || '12px',
color: color || '#333333',
},
}, fiatDisplayNumber),
h('div', {
style: {
color: color || '#AEAEAE',
marginLeft: '5px',
fontSize: fontSize || '12px',
},
}, fiatSuffix),
])
} else {
return h('div')
}
}

View File

@ -1,2 +0,0 @@
import InfoBox from './info-box.component'
module.exports = InfoBox

View File

@ -1,24 +0,0 @@
.info-box {
border-radius: 4px;
background-color: $alabaster;
position: relative;
padding: 16px;
display: flex;
flex-flow: column;
color: $mid-gray;
&__close::after {
content: '\00D7';
font-size: 29px;
font-weight: 200;
color: $dusty-gray;
position: absolute;
right: 12px;
top: 0;
cursor: pointer;
}
&__description {
font-size: .75rem;
}
}

View File

@ -1,49 +0,0 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
export default class InfoBox extends Component {
static contextTypes = {
t: PropTypes.func,
}
static propTypes = {
onClose: PropTypes.func,
title: PropTypes.string,
description: PropTypes.string,
}
constructor (props) {
super(props)
this.state = {
isShowing: true,
}
}
handleClose () {
const { onClose } = this.props
if (onClose) {
onClose()
} else {
this.setState({ isShowing: false })
}
}
render () {
const { title, description } = this.props
return !this.state.isShowing
? null
: (
<div className="info-box">
<div
className="info-box__close"
onClick={() => this.handleClose()}
/>
<div className="info-box__title">{ title }</div>
<div className="info-box__description">{ description }</div>
</div>
)
}
}

View File

@ -1,134 +0,0 @@
const Component = require('react').Component
const h = require('react-hyperscript')
const inherits = require('util').inherits
const findDOMNode = require('react-dom').findDOMNode
import { CSSTransitionGroup } from 'react-transition-group'
module.exports = MenuDroppoComponent
inherits(MenuDroppoComponent, Component)
function MenuDroppoComponent () {
Component.call(this)
}
MenuDroppoComponent.prototype.render = function () {
const { containerClassName = '' } = this.props
const speed = this.props.speed || '300ms'
const useCssTransition = this.props.useCssTransition
const zIndex = ('zIndex' in this.props) ? this.props.zIndex : 0
this.manageListeners()
const style = this.props.style || {}
if (!('position' in style)) {
style.position = 'fixed'
}
style.zIndex = zIndex
return (
h('div', {
style,
className: `.menu-droppo-container ${containerClassName}`,
}, [
h('style', `
.menu-droppo-enter {
transition: transform ${speed} ease-in-out;
transform: translateY(-200%);
}
.menu-droppo-enter.menu-droppo-enter-active {
transition: transform ${speed} ease-in-out;
transform: translateY(0%);
}
.menu-droppo-leave {
transition: transform ${speed} ease-in-out;
transform: translateY(0%);
}
.menu-droppo-leave.menu-droppo-leave-active {
transition: transform ${speed} ease-in-out;
transform: translateY(-200%);
}
`),
useCssTransition
? h(CSSTransitionGroup, {
className: 'css-transition-group',
transitionName: 'menu-droppo',
transitionEnterTimeout: parseInt(speed),
transitionLeaveTimeout: parseInt(speed),
}, this.renderPrimary())
: this.renderPrimary(),
])
)
}
MenuDroppoComponent.prototype.renderPrimary = function () {
const isOpen = this.props.isOpen
if (!isOpen) {
return null
}
const innerStyle = this.props.innerStyle || {}
return (
h('.menu-droppo', {
key: 'menu-droppo-drawer',
style: innerStyle,
},
[ this.props.children ])
)
}
MenuDroppoComponent.prototype.manageListeners = function () {
const isOpen = this.props.isOpen
const onClickOutside = this.props.onClickOutside
if (isOpen) {
this.outsideClickHandler = onClickOutside
} else if (isOpen) {
this.outsideClickHandler = null
}
}
MenuDroppoComponent.prototype.componentDidMount = function () {
if (this && document.body) {
this.globalClickHandler = this.globalClickOccurred.bind(this)
document.body.addEventListener('click', this.globalClickHandler)
// eslint-disable-next-line react/no-find-dom-node
var container = findDOMNode(this)
this.container = container
}
}
MenuDroppoComponent.prototype.componentWillUnmount = function () {
if (this && document.body) {
document.body.removeEventListener('click', this.globalClickHandler)
}
}
MenuDroppoComponent.prototype.globalClickOccurred = function (event) {
const target = event.target
// eslint-disable-next-line react/no-find-dom-node
const container = findDOMNode(this)
if (target !== container &&
!isDescendant(this.container, event.target) &&
this.outsideClickHandler) {
this.outsideClickHandler(event)
}
}
function isDescendant (parent, child) {
var node = child.parentNode
while (node !== null) {
if (node === parent) {
return true
}
node = node.parentNode
}
return false
}

View File

@ -1,220 +0,0 @@
const Component = require('react').Component
const PropTypes = require('prop-types')
const h = require('react-hyperscript')
const inherits = require('util').inherits
const connect = require('react-redux').connect
const actions = require('../../actions')
const { getNetworkDisplayName } = require('../../../../app/scripts/controllers/network/util')
const ShapeshiftForm = require('../shapeshift-form')
import Button from '../button'
let DIRECT_DEPOSIT_ROW_TITLE
let DIRECT_DEPOSIT_ROW_TEXT
let COINBASE_ROW_TITLE
let COINBASE_ROW_TEXT
let SHAPESHIFT_ROW_TITLE
let SHAPESHIFT_ROW_TEXT
let FAUCET_ROW_TITLE
function mapStateToProps (state) {
return {
network: state.metamask.network,
address: state.metamask.selectedAddress,
}
}
function mapDispatchToProps (dispatch) {
return {
toCoinbase: (address) => {
dispatch(actions.buyEth({ network: '1', address, amount: 0 }))
},
hideModal: () => {
dispatch(actions.hideModal())
},
hideWarning: () => {
dispatch(actions.hideWarning())
},
showAccountDetailModal: () => {
dispatch(actions.showModal({ name: 'ACCOUNT_DETAILS' }))
},
toFaucet: network => dispatch(actions.buyEth({ network })),
}
}
inherits(DepositEtherModal, Component)
function DepositEtherModal (props, context) {
Component.call(this)
// need to set after i18n locale has loaded
DIRECT_DEPOSIT_ROW_TITLE = context.t('directDepositEther')
DIRECT_DEPOSIT_ROW_TEXT = context.t('directDepositEtherExplainer')
COINBASE_ROW_TITLE = context.t('buyCoinbase')
COINBASE_ROW_TEXT = context.t('buyCoinbaseExplainer')
SHAPESHIFT_ROW_TITLE = context.t('depositShapeShift')
SHAPESHIFT_ROW_TEXT = context.t('depositShapeShiftExplainer')
FAUCET_ROW_TITLE = context.t('testFaucet')
this.state = {
buyingWithShapeshift: false,
}
}
DepositEtherModal.contextTypes = {
t: PropTypes.func,
}
module.exports = connect(mapStateToProps, mapDispatchToProps)(DepositEtherModal)
DepositEtherModal.prototype.facuetRowText = function (networkName) {
return this.context.t('getEtherFromFaucet', [networkName])
}
DepositEtherModal.prototype.renderRow = function ({
logo,
title,
text,
buttonLabel,
onButtonClick,
hide,
className,
hideButton,
hideTitle,
onBackClick,
showBackButton,
}) {
if (hide) {
return null
}
return h('div', {
className: className || 'deposit-ether-modal__buy-row',
}, [
onBackClick && showBackButton && h('div.deposit-ether-modal__buy-row__back', {
onClick: onBackClick,
}, [
h('i.fa.fa-arrow-left.cursor-pointer'),
]),
h('div.deposit-ether-modal__buy-row__logo-container', [logo]),
h('div.deposit-ether-modal__buy-row__description', [
!hideTitle && h('div.deposit-ether-modal__buy-row__description__title', [title]),
h('div.deposit-ether-modal__buy-row__description__text', [text]),
]),
!hideButton && h('div.deposit-ether-modal__buy-row__button', [
h(Button, {
type: 'primary',
className: 'deposit-ether-modal__deposit-button',
large: true,
onClick: onButtonClick,
}, [buttonLabel]),
]),
])
}
DepositEtherModal.prototype.render = function () {
const { network, toCoinbase, address, toFaucet } = this.props
const { buyingWithShapeshift } = this.state
const isTestNetwork = ['3', '4', '42'].find(n => n === network)
const networkName = getNetworkDisplayName(network)
return h('div.page-container.page-container--full-width.page-container--full-height', {}, [
h('div.page-container__header', [
h('div.page-container__title', [this.context.t('depositEther')]),
h('div.page-container__subtitle', [
this.context.t('needEtherInWallet'),
]),
h('div.page-container__header-close', {
onClick: () => {
this.setState({ buyingWithShapeshift: false })
this.props.hideWarning()
this.props.hideModal()
},
}),
]),
h('.page-container__content', {}, [
h('div.deposit-ether-modal__buy-rows', [
this.renderRow({
logo: h('img.deposit-ether-modal__logo', {
src: './images/deposit-eth.svg',
}),
title: DIRECT_DEPOSIT_ROW_TITLE,
text: DIRECT_DEPOSIT_ROW_TEXT,
buttonLabel: this.context.t('viewAccount'),
onButtonClick: () => this.goToAccountDetailsModal(),
hide: buyingWithShapeshift,
}),
this.renderRow({
logo: h('i.fa.fa-tint.fa-2x'),
title: FAUCET_ROW_TITLE,
text: this.facuetRowText(networkName),
buttonLabel: this.context.t('getEther'),
onButtonClick: () => toFaucet(network),
hide: !isTestNetwork || buyingWithShapeshift,
}),
this.renderRow({
logo: h('div.deposit-ether-modal__logo', {
style: {
backgroundImage: 'url(\'./images/coinbase logo.png\')',
height: '40px',
},
}),
title: COINBASE_ROW_TITLE,
text: COINBASE_ROW_TEXT,
buttonLabel: this.context.t('continueToCoinbase'),
onButtonClick: () => toCoinbase(address),
hide: isTestNetwork || buyingWithShapeshift,
}),
this.renderRow({
logo: h('div.deposit-ether-modal__logo', {
style: {
backgroundImage: 'url(\'./images/shapeshift logo.png\')',
},
}),
title: SHAPESHIFT_ROW_TITLE,
text: SHAPESHIFT_ROW_TEXT,
buttonLabel: this.context.t('shapeshiftBuy'),
onButtonClick: () => this.setState({ buyingWithShapeshift: true }),
hide: isTestNetwork,
hideButton: buyingWithShapeshift,
hideTitle: buyingWithShapeshift,
onBackClick: () => this.setState({ buyingWithShapeshift: false }),
showBackButton: this.state.buyingWithShapeshift,
className: buyingWithShapeshift && 'deposit-ether-modal__buy-row__shapeshift-buy',
}),
buyingWithShapeshift && h(ShapeshiftForm),
]),
]),
])
}
DepositEtherModal.prototype.goToAccountDetailsModal = function () {
this.props.hideWarning()
this.props.hideModal()
this.props.showAccountDetailModal()
}

View File

@ -10,7 +10,6 @@ const { ENVIRONMENT_TYPE_POPUP } = require('../../../../app/scripts/lib/enums')
// Modal Components
const BuyOptions = require('./buy-options-modal')
const DepositEtherModal = require('./deposit-ether-modal')
const EditAccountNameModal = require('./edit-account-name-modal')
const ExportPrivateKeyModal = require('./export-private-key-modal')
const NewAccountModal = require('./new-account-modal')
@ -72,40 +71,6 @@ const MODALS = {
},
},
DEPOSIT_ETHER: {
contents: [
h(DepositEtherModal, {}, []),
],
onHide: (props) => props.hideWarning(),
mobileModalStyle: {
width: '100%',
height: '100%',
transform: 'none',
left: '0',
right: '0',
margin: '0 auto',
boxShadow: '0 0 7px 0 rgba(0,0,0,0.08)',
top: '0',
display: 'flex',
},
laptopModalStyle: {
width: '850px',
top: 'calc(10% + 10px)',
left: '0',
right: '0',
margin: '0 auto',
boxShadow: '0 0 6px 0 rgba(0,0,0,0.3)',
borderRadius: '7px',
transform: 'none',
height: 'calc(80% - 20px)',
overflowY: 'hidden',
},
contentStyle: {
borderRadius: '7px',
height: '100%',
},
},
EDIT_ACCOUNT_NAME: {
contents: [
h(EditAccountNameModal, {}, []),

View File

@ -1,138 +0,0 @@
const inherits = require('util').inherits
const Component = require('react').Component
const PropTypes = require('prop-types')
const h = require('react-hyperscript')
const ReactMarkdown = require('react-markdown')
const linker = require('extension-link-enabler')
const findDOMNode = require('react-dom').findDOMNode
const connect = require('react-redux').connect
Notice.contextTypes = {
t: PropTypes.func,
}
module.exports = connect()(Notice)
inherits(Notice, Component)
function Notice () {
Component.call(this)
}
Notice.prototype.render = function () {
const { notice, onConfirm } = this.props
const { title, date, body } = notice
const state = this.state || { disclaimerDisabled: true }
const disabled = state.disclaimerDisabled
return (
h('.flex-column.flex-center.flex-grow', {
style: {
width: '100%',
},
}, [
h('h3.flex-center.text-transform-uppercase.terms-header', {
style: {
background: '#EBEBEB',
color: '#AEAEAE',
width: '100%',
fontSize: '20px',
textAlign: 'center',
padding: 6,
},
}, [
title,
]),
h('h5.flex-center.text-transform-uppercase.terms-header', {
style: {
background: '#EBEBEB',
color: '#AEAEAE',
marginBottom: 24,
width: '100%',
fontSize: '20px',
textAlign: 'center',
padding: 6,
},
}, [
date,
]),
h('style', `
.markdown {
overflow-x: hidden;
}
.markdown h1, .markdown h2, .markdown h3 {
margin: 10px 0;
font-weight: bold;
}
.markdown strong {
font-weight: bold;
}
.markdown em {
font-style: italic;
}
.markdown p {
margin: 10px 0;
}
.markdown a {
color: #df6b0e;
}
`),
h('div.markdown', {
onScroll: (e) => {
var object = e.currentTarget
if (object.offsetHeight + object.scrollTop + 100 >= object.scrollHeight) {
this.setState({disclaimerDisabled: false})
}
},
style: {
background: 'rgb(235, 235, 235)',
height: '310px',
padding: '6px',
width: '90%',
overflowY: 'scroll',
scroll: 'auto',
},
}, [
h(ReactMarkdown, {
className: 'notice-box',
source: body,
skipHtml: true,
}),
]),
h('button.primary', {
disabled,
onClick: () => {
this.setState({disclaimerDisabled: true}, () => onConfirm())
},
style: {
marginTop: '18px',
},
}, this.context.t('accept')),
])
)
}
Notice.prototype.componentDidMount = function () {
// eslint-disable-next-line react/no-find-dom-node
var node = findDOMNode(this)
linker.setupListener(node)
if (document.getElementsByClassName('notice-box')[0].clientHeight < 310) {
this.setState({disclaimerDisabled: false})
}
}
Notice.prototype.componentWillUnmount = function () {
// eslint-disable-next-line react/no-find-dom-node
var node = findDOMNode(this)
linker.teardownListener(node)
}

View File

@ -1,77 +0,0 @@
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import Media from 'react-media'
import { Redirect } from 'react-router-dom'
import WalletView from '../../wallet-view'
import TransactionView from '../../transaction-view'
import {
INITIALIZE_BACKUP_PHRASE_ROUTE,
RESTORE_VAULT_ROUTE,
CONFIRM_TRANSACTION_ROUTE,
NOTICE_ROUTE,
CONFIRM_ADD_SUGGESTED_TOKEN_ROUTE,
} from '../../../routes'
export default class Home extends PureComponent {
static propTypes = {
history: PropTypes.object,
noActiveNotices: PropTypes.bool,
lostAccounts: PropTypes.array,
forgottenPassword: PropTypes.bool,
seedWords: PropTypes.string,
suggestedTokens: PropTypes.object,
unconfirmedTransactionsCount: PropTypes.number,
}
componentDidMount () {
const {
history,
suggestedTokens = {},
unconfirmedTransactionsCount = 0,
} = this.props
// suggested new tokens
if (Object.keys(suggestedTokens).length > 0) {
history.push(CONFIRM_ADD_SUGGESTED_TOKEN_ROUTE)
}
if (unconfirmedTransactionsCount > 0) {
history.push(CONFIRM_TRANSACTION_ROUTE)
}
}
render () {
const {
noActiveNotices,
lostAccounts,
forgottenPassword,
seedWords,
} = this.props
// notices
if (!noActiveNotices || (lostAccounts && lostAccounts.length > 0)) {
return <Redirect to={{ pathname: NOTICE_ROUTE }} />
}
// seed words
if (seedWords) {
return <Redirect to={{ pathname: INITIALIZE_BACKUP_PHRASE_ROUTE }}/>
}
if (forgottenPassword) {
return <Redirect to={{ pathname: RESTORE_VAULT_ROUTE }} />
}
return (
<div className="main-container">
<div className="account-and-transaction-details">
<Media
query="(min-width: 576px)"
render={() => <WalletView />}
/>
<TransactionView />
</div>
</div>
)
}
}

View File

@ -1,30 +0,0 @@
import Home from './home.component'
import { compose } from 'recompose'
import { connect } from 'react-redux'
import { withRouter } from 'react-router-dom'
import { unconfirmedTransactionsCountSelector } from '../../../selectors/confirm-transaction'
const mapStateToProps = state => {
const { metamask, appState } = state
const {
noActiveNotices,
lostAccounts,
seedWords,
suggestedTokens,
} = metamask
const { forgottenPassword } = appState
return {
noActiveNotices,
lostAccounts,
forgottenPassword,
seedWords,
suggestedTokens,
unconfirmedTransactionsCount: unconfirmedTransactionsCountSelector(state),
}
}
export default compose(
withRouter,
connect(mapStateToProps)
)(Home)

View File

@ -1 +0,0 @@
export { default } from './home.container'

View File

@ -1,189 +0,0 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import {
createNewVaultAndRestore,
unMarkPasswordForgotten,
} from '../../../actions'
import { DEFAULT_ROUTE } from '../../../routes'
import TextField from '../../text-field'
class RestoreVaultPage extends Component {
static contextTypes = {
t: PropTypes.func,
}
static propTypes = {
warning: PropTypes.string,
createNewVaultAndRestore: PropTypes.func.isRequired,
leaveImportSeedScreenState: PropTypes.func,
history: PropTypes.object,
isLoading: PropTypes.bool,
};
state = {
seedPhrase: '',
password: '',
confirmPassword: '',
seedPhraseError: null,
passwordError: null,
confirmPasswordError: null,
}
parseSeedPhrase = (seedPhrase) => {
return seedPhrase
.match(/\w+/g)
.join(' ')
}
handleSeedPhraseChange (seedPhrase) {
let seedPhraseError = null
if (seedPhrase && this.parseSeedPhrase(seedPhrase).split(' ').length !== 12) {
seedPhraseError = this.context.t('seedPhraseReq')
}
this.setState({ seedPhrase, seedPhraseError })
}
handlePasswordChange (password) {
const { confirmPassword } = this.state
let confirmPasswordError = null
let passwordError = null
if (password && password.length < 8) {
passwordError = this.context.t('passwordNotLongEnough')
}
if (confirmPassword && password !== confirmPassword) {
confirmPasswordError = this.context.t('passwordsDontMatch')
}
this.setState({ password, passwordError, confirmPasswordError })
}
handleConfirmPasswordChange (confirmPassword) {
const { password } = this.state
let confirmPasswordError = null
if (password !== confirmPassword) {
confirmPasswordError = this.context.t('passwordsDontMatch')
}
this.setState({ confirmPassword, confirmPasswordError })
}
onClick = () => {
const { password, seedPhrase } = this.state
const {
createNewVaultAndRestore,
leaveImportSeedScreenState,
history,
} = this.props
leaveImportSeedScreenState()
createNewVaultAndRestore(password, this.parseSeedPhrase(seedPhrase))
.then(() => history.push(DEFAULT_ROUTE))
}
hasError () {
const { passwordError, confirmPasswordError, seedPhraseError } = this.state
return passwordError || confirmPasswordError || seedPhraseError
}
render () {
const {
seedPhrase,
password,
confirmPassword,
seedPhraseError,
passwordError,
confirmPasswordError,
} = this.state
const { t } = this.context
const { isLoading } = this.props
const disabled = !seedPhrase || !password || !confirmPassword || isLoading || this.hasError()
return (
<div className="first-view-main-wrapper">
<div className="first-view-main">
<div className="import-account">
<a
className="import-account__back-button"
onClick={e => {
e.preventDefault()
this.props.history.goBack()
}}
href="#"
>
{`< Back`}
</a>
<div className="import-account__title">
{ this.context.t('restoreAccountWithSeed') }
</div>
<div className="import-account__selector-label">
{ this.context.t('secretPhrase') }
</div>
<div className="import-account__input-wrapper">
<label className="import-account__input-label">Wallet Seed</label>
<textarea
className="import-account__secret-phrase"
onChange={e => this.handleSeedPhraseChange(e.target.value)}
value={this.state.seedPhrase}
placeholder={this.context.t('separateEachWord')}
/>
</div>
<span className="error">
{ seedPhraseError }
</span>
<TextField
id="password"
label={t('newPassword')}
type="password"
className="first-time-flow__input"
value={this.state.password}
onChange={event => this.handlePasswordChange(event.target.value)}
error={passwordError}
autoComplete="new-password"
margin="normal"
largeLabel
/>
<TextField
id="confirm-password"
label={t('confirmPassword')}
type="password"
className="first-time-flow__input"
value={this.state.confirmPassword}
onChange={event => this.handleConfirmPasswordChange(event.target.value)}
error={confirmPasswordError}
autoComplete="confirm-password"
margin="normal"
largeLabel
/>
<button
className="first-time-flow__button"
onClick={() => !disabled && this.onClick()}
disabled={disabled}
>
{this.context.t('restore')}
</button>
</div>
</div>
</div>
)
}
}
RestoreVaultPage.contextTypes = {
t: PropTypes.func,
}
export default connect(
({ appState: { warning, isLoading } }) => ({ warning, isLoading }),
dispatch => ({
leaveImportSeedScreenState: () => {
dispatch(unMarkPasswordForgotten())
},
createNewVaultAndRestore: (pw, seed) => dispatch(createNewVaultAndRestore(pw, seed)),
})
)(RestoreVaultPage)

View File

@ -1,177 +0,0 @@
const { Component } = require('react')
const { connect } = require('react-redux')
const PropTypes = require('prop-types')
const h = require('react-hyperscript')
const classnames = require('classnames')
const { requestRevealSeedWords } = require('../../../actions')
const { DEFAULT_ROUTE } = require('../../../routes')
const ExportTextContainer = require('../../export-text-container')
import Button from '../../button'
const PASSWORD_PROMPT_SCREEN = 'PASSWORD_PROMPT_SCREEN'
const REVEAL_SEED_SCREEN = 'REVEAL_SEED_SCREEN'
class RevealSeedPage extends Component {
constructor (props) {
super(props)
this.state = {
screen: PASSWORD_PROMPT_SCREEN,
password: '',
seedWords: null,
error: null,
}
}
componentDidMount () {
const passwordBox = document.getElementById('password-box')
if (passwordBox) {
passwordBox.focus()
}
}
handleSubmit (event) {
event.preventDefault()
this.setState({ seedWords: null, error: null })
this.props.requestRevealSeedWords(this.state.password)
.then(seedWords => this.setState({ seedWords, screen: REVEAL_SEED_SCREEN }))
.catch(error => this.setState({ error: error.message }))
}
renderWarning () {
return (
h('.page-container__warning-container', [
h('img.page-container__warning-icon', {
src: 'images/warning.svg',
}),
h('.page-container__warning-message', [
h('.page-container__warning-title', [this.context.t('revealSeedWordsWarningTitle')]),
h('div', [this.context.t('revealSeedWordsWarning')]),
]),
])
)
}
renderContent () {
return this.state.screen === PASSWORD_PROMPT_SCREEN
? this.renderPasswordPromptContent()
: this.renderRevealSeedContent()
}
renderPasswordPromptContent () {
const { t } = this.context
return (
h('form', {
onSubmit: event => this.handleSubmit(event),
}, [
h('label.input-label', {
htmlFor: 'password-box',
}, t('enterPasswordContinue')),
h('.input-group', [
h('input.form-control', {
type: 'password',
placeholder: t('password'),
id: 'password-box',
value: this.state.password,
onChange: event => this.setState({ password: event.target.value }),
className: classnames({ 'form-control--error': this.state.error }),
}),
]),
this.state.error && h('.reveal-seed__error', this.state.error),
])
)
}
renderRevealSeedContent () {
const { t } = this.context
return (
h('div', [
h('label.reveal-seed__label', t('yourPrivateSeedPhrase')),
h(ExportTextContainer, {
text: this.state.seedWords,
filename: t('metamaskSeedWords'),
}),
])
)
}
renderFooter () {
return this.state.screen === PASSWORD_PROMPT_SCREEN
? this.renderPasswordPromptFooter()
: this.renderRevealSeedFooter()
}
renderPasswordPromptFooter () {
return (
h('.page-container__footer', [
h('header', [
h(Button, {
type: 'default',
large: true,
className: 'page-container__footer-button',
onClick: () => this.props.history.push(DEFAULT_ROUTE),
}, this.context.t('cancel')),
h(Button, {
type: 'primary',
large: true,
className: 'page-container__footer-button',
onClick: event => this.handleSubmit(event),
disabled: this.state.password === '',
}, this.context.t('next')),
]),
])
)
}
renderRevealSeedFooter () {
return (
h('.page-container__footer', [
h(Button, {
type: 'default',
large: true,
className: 'page-container__footer-button',
onClick: () => this.props.history.push(DEFAULT_ROUTE),
}, this.context.t('close')),
])
)
}
render () {
return (
h('.page-container', [
h('.page-container__header', [
h('.page-container__title', this.context.t('revealSeedWordsTitle')),
h('.page-container__subtitle', this.context.t('revealSeedWordsDescription')),
]),
h('.page-container__content', [
this.renderWarning(),
h('.reveal-seed__content', [
this.renderContent(),
]),
]),
this.renderFooter(),
])
)
}
}
RevealSeedPage.propTypes = {
requestRevealSeedWords: PropTypes.func,
history: PropTypes.object,
}
RevealSeedPage.contextTypes = {
t: PropTypes.func,
}
const mapDispatchToProps = dispatch => {
return {
requestRevealSeedWords: password => dispatch(requestRevealSeedWords(password)),
}
}
module.exports = connect(null, mapDispatchToProps)(RevealSeedPage)

View File

@ -1 +0,0 @@
export { default } from './sender-to-recipient.component'

View File

@ -1,120 +0,0 @@
.sender-to-recipient {
&--default {
width: 100%;
display: flex;
flex-direction: row;
justify-content: center;
border-bottom: 1px solid $geyser;
position: relative;
flex: 0 0 auto;
height: 42px;
.sender-to-recipient {
&__tooltip-wrapper {
min-width: 0;
}
&__tooltip-container {
max-width: 100%;
}
&__party {
display: flex;
flex-direction: row;
align-items: center;
flex: 1;
padding: 0 16px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
&--sender {
padding-right: 30px;
cursor: pointer;
}
&--recipient {
padding-left: 30px;
border-left: 1px solid $geyser;
&-with-address {
cursor: pointer;
}
}
}
&__arrow-container {
position: absolute;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
&__arrow-circle {
background: $white;
padding: 5px;
border: 1px solid $geyser;
border-radius: 20px;
height: 32px;
width: 32px;
display: flex;
justify-content: center;
align-items: center;
}
&__name {
padding-left: 14px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: .875rem;
}
}
}
&--cards {
width: 100%;
display: flex;
flex-direction: row;
justify-content: center;
position: relative;
flex: 0 0 auto;
.sender-to-recipient {
&__party {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
flex: 1;
border-radius: 4px;
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.08);
padding: 6px;
background: $white;
cursor: pointer;
min-width: 0;
color: $dusty-gray;
}
&__tooltip-wrapper {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&__name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: .5rem;
}
&__arrow-container {
display: flex;
justify-content: center;
align-items: center;
}
}
}
}

View File

@ -1,177 +0,0 @@
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames'
import Identicon from '../identicon'
import Tooltip from '../tooltip-v2'
import copyToClipboard from 'copy-to-clipboard'
import { DEFAULT_VARIANT, CARDS_VARIANT } from './sender-to-recipient.constants'
import { checksumAddress } from '../../util'
const variantHash = {
[DEFAULT_VARIANT]: 'sender-to-recipient--default',
[CARDS_VARIANT]: 'sender-to-recipient--cards',
}
export default class SenderToRecipient extends PureComponent {
static propTypes = {
senderName: PropTypes.string,
senderAddress: PropTypes.string,
recipientName: PropTypes.string,
recipientAddress: PropTypes.string,
t: PropTypes.func,
variant: PropTypes.oneOf([DEFAULT_VARIANT, CARDS_VARIANT]),
addressOnly: PropTypes.bool,
assetImage: PropTypes.string,
}
static defaultProps = {
variant: DEFAULT_VARIANT,
}
static contextTypes = {
t: PropTypes.func,
}
state = {
senderAddressCopied: false,
recipientAddressCopied: false,
}
renderSenderIdenticon () {
return !this.props.addressOnly && (
<div className="sender-to-recipient__sender-icon">
<Identicon
address={checksumAddress(this.props.senderAddress)}
diameter={24}
/>
</div>
)
}
renderSenderAddress () {
const { t } = this.context
const { senderName, senderAddress, addressOnly } = this.props
const checksummedSenderAddress = checksumAddress(senderAddress)
return (
<Tooltip
position="bottom"
title={this.state.senderAddressCopied ? t('copiedExclamation') : t('copyAddress')}
wrapperClassName="sender-to-recipient__tooltip-wrapper"
containerClassName="sender-to-recipient__tooltip-container"
onHidden={() => this.setState({ senderAddressCopied: false })}
>
<div className="sender-to-recipient__name">
{ addressOnly ? `${t('from')}: ${checksummedSenderAddress}` : senderName }
</div>
</Tooltip>
)
}
renderRecipientIdenticon () {
const { recipientAddress, assetImage } = this.props
const checksummedRecipientAddress = checksumAddress(recipientAddress)
return !this.props.addressOnly && (
<div className="sender-to-recipient__sender-icon">
<Identicon
address={checksummedRecipientAddress}
diameter={24}
image={assetImage}
/>
</div>
)
}
renderRecipientWithAddress () {
const { t } = this.context
const { recipientName, recipientAddress, addressOnly } = this.props
const checksummedRecipientAddress = checksumAddress(recipientAddress)
return (
<div
className="sender-to-recipient__party sender-to-recipient__party--recipient sender-to-recipient__party--recipient-with-address"
onClick={() => {
this.setState({ recipientAddressCopied: true })
copyToClipboard(checksummedRecipientAddress)
}}
>
{ this.renderRecipientIdenticon() }
<Tooltip
position="bottom"
title={this.state.recipientAddressCopied ? t('copiedExclamation') : t('copyAddress')}
wrapperClassName="sender-to-recipient__tooltip-wrapper"
containerClassName="sender-to-recipient__tooltip-container"
onHidden={() => this.setState({ recipientAddressCopied: false })}
>
<div className="sender-to-recipient__name">
{
addressOnly
? `${t('to')}: ${checksummedRecipientAddress}`
: (recipientName || this.context.t('newContract'))
}
</div>
</Tooltip>
</div>
)
}
renderRecipientWithoutAddress () {
return (
<div className="sender-to-recipient__party sender-to-recipient__party--recipient">
{ !this.props.addressOnly && <i className="fa fa-file-text-o" /> }
<div className="sender-to-recipient__name">
{ this.context.t('newContract') }
</div>
</div>
)
}
renderArrow () {
return this.props.variant === CARDS_VARIANT
? (
<div className="sender-to-recipient__arrow-container">
<img
height={20}
src="./images/caret-right.svg"
/>
</div>
) : (
<div className="sender-to-recipient__arrow-container">
<div className="sender-to-recipient__arrow-circle">
<img
height={15}
width={15}
src="./images/arrow-right.svg"
/>
</div>
</div>
)
}
render () {
const { senderAddress, recipientAddress, variant } = this.props
const checksummedSenderAddress = checksumAddress(senderAddress)
return (
<div className={classnames(variantHash[variant])}>
<div
className={classnames('sender-to-recipient__party sender-to-recipient__party--sender')}
onClick={() => {
this.setState({ senderAddressCopied: true })
copyToClipboard(checksummedSenderAddress)
}}
>
{ this.renderSenderIdenticon() }
{ this.renderSenderAddress() }
</div>
{ this.renderArrow() }
{
recipientAddress
? this.renderRecipientWithAddress()
: this.renderRecipientWithoutAddress()
}
</div>
)
}
}

View File

@ -1,3 +0,0 @@
// Component design variants
export const DEFAULT_VARIANT = 'DEFAULT_VARIANT'
export const CARDS_VARIANT = 'CARDS_VARIANT'

View File

@ -1,256 +0,0 @@
const h = require('react-hyperscript')
const inherits = require('util').inherits
const PropTypes = require('prop-types')
const Component = require('react').Component
const connect = require('react-redux').connect
const classnames = require('classnames')
const { qrcode } = require('qrcode-npm')
const { shapeShiftSubview, pairUpdate, buyWithShapeShift } = require('../actions')
const { isValidAddress } = require('../util')
const SimpleDropdown = require('./dropdowns/simple-dropdown')
import Button from './button'
function mapStateToProps (state) {
const {
coinOptions,
tokenExchangeRates,
selectedAddress,
} = state.metamask
const { warning } = state.appState
return {
coinOptions,
tokenExchangeRates,
selectedAddress,
warning,
}
}
function mapDispatchToProps (dispatch) {
return {
shapeShiftSubview: () => dispatch(shapeShiftSubview()),
pairUpdate: coin => dispatch(pairUpdate(coin)),
buyWithShapeShift: data => dispatch(buyWithShapeShift(data)),
}
}
ShapeshiftForm.contextTypes = {
t: PropTypes.func,
}
module.exports = connect(mapStateToProps, mapDispatchToProps)(ShapeshiftForm)
inherits(ShapeshiftForm, Component)
function ShapeshiftForm () {
Component.call(this)
this.state = {
depositCoin: 'btc',
refundAddress: '',
showQrCode: false,
depositAddress: '',
errorMessage: '',
isLoading: false,
bought: false,
}
}
ShapeshiftForm.prototype.getCoinPair = function () {
return `${this.state.depositCoin.toUpperCase()}_ETH`
}
ShapeshiftForm.prototype.componentWillMount = function () {
this.props.shapeShiftSubview()
}
ShapeshiftForm.prototype.onCoinChange = function (coin) {
this.setState({
depositCoin: coin,
errorMessage: '',
})
this.props.pairUpdate(coin)
}
ShapeshiftForm.prototype.onBuyWithShapeShift = function () {
this.setState({
isLoading: true,
showQrCode: true,
})
const {
buyWithShapeShift,
selectedAddress: withdrawal,
} = this.props
const {
refundAddress: returnAddress,
depositCoin,
} = this.state
const pair = `${depositCoin}_eth`
const data = {
withdrawal,
pair,
returnAddress,
// Public api key
'apiKey': '5efdee9e7d3c99e7c7e8a0f788d6e52205bf00a0e24575fe59df86421f63c477d018840c94f6596cf8946990216073c68144394c384b0ddcbe782351d80d61d7',
}
if (isValidAddress(withdrawal)) {
buyWithShapeShift(data)
.then(d => this.setState({
showQrCode: true,
depositAddress: d.deposit,
isLoading: false,
}))
.catch(() => this.setState({
showQrCode: false,
errorMessage: this.context.t('invalidRequest'),
isLoading: false,
}))
}
}
ShapeshiftForm.prototype.renderMetadata = function (label, value) {
return h('div', {className: 'shapeshift-form__metadata-wrapper'}, [
h('div.shapeshift-form__metadata-label', {}, [
h('span', `${label}:`),
]),
h('div.shapeshift-form__metadata-value', {}, [
h('span', value),
]),
])
}
ShapeshiftForm.prototype.renderMarketInfo = function () {
const { tokenExchangeRates } = this.props
const {
limit,
rate,
minimum,
} = tokenExchangeRates[this.getCoinPair()] || {}
return h('div.shapeshift-form__metadata', {}, [
this.renderMetadata(this.context.t('status'), limit ? this.context.t('available') : this.context.t('unavailable')),
this.renderMetadata(this.context.t('limit'), limit),
this.renderMetadata(this.context.t('exchangeRate'), rate),
this.renderMetadata(this.context.t('min'), minimum),
])
}
ShapeshiftForm.prototype.renderQrCode = function () {
const { depositAddress, isLoading, depositCoin } = this.state
const qrImage = qrcode(4, 'M')
qrImage.addData(depositAddress)
qrImage.make()
return h('div.shapeshift-form', {}, [
h('div.shapeshift-form__deposit-instruction', [
this.context.t('depositCoin', [depositCoin.toUpperCase()]),
]),
h('div', depositAddress),
h('div.shapeshift-form__qr-code', [
isLoading
? h('img', {
src: 'images/loading.svg',
style: { width: '60px'},
})
: h('div', {
dangerouslySetInnerHTML: { __html: qrImage.createTableTag(4) },
}),
]),
this.renderMarketInfo(),
])
}
ShapeshiftForm.prototype.render = function () {
const { coinOptions, btnClass, warning } = this.props
const { errorMessage, showQrCode, depositAddress } = this.state
const { tokenExchangeRates } = this.props
const token = tokenExchangeRates[this.getCoinPair()]
return h('div.shapeshift-form-wrapper', [
showQrCode
? this.renderQrCode()
: h('div.modal-shapeshift-form', [
h('div.shapeshift-form__selectors', [
h('div.shapeshift-form__selector', [
h('div.shapeshift-form__selector-label', this.context.t('deposit')),
h(SimpleDropdown, {
selectedOption: this.state.depositCoin,
onSelect: (coin) => this.onCoinChange(coin),
options: Object.entries(coinOptions).map(([coin]) => ({
value: coin.toLowerCase(),
displayValue: coin,
})),
}),
]),
h('div.icon.shapeshift-form__caret', {
style: { backgroundImage: 'url(images/caret-right.svg)'},
}),
h('div.shapeshift-form__selector', [
h('div.shapeshift-form__selector-label', [
this.context.t('receive'),
]),
h('div.shapeshift-form__selector-input', ['ETH']),
]),
]),
warning && h('div.shapeshift-form__address-input-label', warning),
!warning && h('div', {
className: classnames('shapeshift-form__address-input-wrapper', {
'shapeshift-form__address-input-wrapper--error': errorMessage,
}),
}, [
h('div.shapeshift-form__address-input-label', [
this.context.t('refundAddress'),
]),
h('input.shapeshift-form__address-input', {
type: 'text',
onChange: e => this.setState({
refundAddress: e.target.value,
errorMessage: '',
}),
}),
h('divshapeshift-form__address-input-error-message', [errorMessage]),
]),
!warning && this.renderMarketInfo(),
]),
!depositAddress && h(Button, {
type: 'primary',
large: true,
className: `${btnClass} shapeshift-form__shapeshift-buy-btn`,
disabled: !token,
onClick: () => this.onBuyWithShapeShift(),
}, [this.context.t('buy')]),
])
}

View File

@ -1,210 +0,0 @@
const inherits = require('util').inherits
const Component = require('react').Component
const PropTypes = require('prop-types')
const h = require('react-hyperscript')
const connect = require('react-redux').connect
const vreme = new (require('vreme'))()
const ethNetProps = require('eth-net-props')
const actions = require('../actions')
const addressSummary = require('../util').addressSummary
const CopyButton = require('./copyButton')
const EthBalance = require('./eth-balance')
const Tooltip = require('./tooltip')
ShiftListItem.contextTypes = {
t: PropTypes.func,
}
module.exports = connect(mapStateToProps)(ShiftListItem)
function mapStateToProps (state) {
return {
selectedAddress: state.metamask.selectedAddress,
conversionRate: state.metamask.conversionRate,
currentCurrency: state.metamask.currentCurrency,
}
}
inherits(ShiftListItem, Component)
function ShiftListItem () {
Component.call(this)
}
ShiftListItem.prototype.render = function () {
return h('div.transaction-list-item.tx-list-clickable', {
style: {
paddingTop: '20px',
paddingBottom: '20px',
justifyContent: 'space-around',
alignItems: 'center',
flexDirection: 'row',
},
}, [
h('div', {
style: {
width: '0px',
position: 'relative',
bottom: '19px',
},
}, [
h('img', {
src: './images/shapeshift-logo-only.png',
style: {
height: '35px',
width: '132px',
position: 'absolute',
clip: 'rect(0px,23px,34px,0px)',
},
}),
]),
this.renderInfo(),
this.renderUtilComponents(),
])
}
function formatDate (date) {
return vreme.format(new Date(date), 'March 16 2014 14:30')
}
ShiftListItem.prototype.renderUtilComponents = function () {
var props = this.props
const { conversionRate, currentCurrency } = props
switch (props.response.status) {
case 'no_deposits':
return h('.flex-row', [
h(CopyButton, {
value: this.props.depositAddress,
}),
h(Tooltip, {
title: this.context.t('qrCode'),
}, [
h('i.fa.fa-qrcode.pointer.pop-hover', {
onClick: () => props.dispatch(actions.reshowQrCode(props.depositAddress, props.depositType)),
style: {
margin: '5px',
marginLeft: '23px',
marginRight: '12px',
fontSize: '20px',
color: '#F7861C',
},
}),
]),
])
case 'received':
return h('.flex-row')
case 'complete':
return h('.flex-row', [
h(CopyButton, {
value: this.props.response.transaction,
}),
h(EthBalance, {
value: `${props.response.outgoingCoin}`,
conversionRate,
currentCurrency,
width: '55px',
shorten: true,
needsParse: false,
incoming: true,
style: {
fontSize: '15px',
color: '#01888C',
},
}),
])
case 'failed':
return ''
default:
return ''
}
}
ShiftListItem.prototype.renderInfo = function () {
var props = this.props
switch (props.response.status) {
case 'no_deposits':
return h('.flex-column', {
style: {
width: '200px',
overflow: 'hidden',
},
}, [
h('div', {
style: {
fontSize: 'x-small',
color: '#ABA9AA',
width: '100%',
},
}, this.context.t('toETHviaShapeShift', [props.depositType])),
h('div', this.context.t('noDeposits')),
h('div', {
style: {
fontSize: 'x-small',
color: '#ABA9AA',
width: '100%',
},
}, formatDate(props.time)),
])
case 'received':
return h('.flex-column', {
style: {
width: '200px',
overflow: 'hidden',
},
}, [
h('div', {
style: {
fontSize: 'x-small',
color: '#ABA9AA',
width: '100%',
},
}, this.context.t('toETHviaShapeShift', [props.depositType])),
h('div', this.context.t('conversionProgress')),
h('div', {
style: {
fontSize: 'x-small',
color: '#ABA9AA',
width: '100%',
},
}, formatDate(props.time)),
])
case 'complete':
var url = ethNetProps.explorerLinks.getExplorerTxLinkFor(props.response.transaction, parseInt('1'))
return h('.flex-column.pointer', {
style: {
width: '200px',
overflow: 'hidden',
},
onClick: () => global.platform.openWindow({ url }),
}, [
h('div', {
style: {
fontSize: 'x-small',
color: '#ABA9AA',
width: '100%',
},
}, this.context.t('fromShapeShift')),
h('div', formatDate(props.time)),
h('div', {
style: {
fontSize: 'x-small',
color: '#ABA9AA',
width: '100%',
},
}, addressSummary(props.response.transaction)),
])
case 'failed':
return h('span.error', '(' + this.context.t('failed') + ')')
default:
return ''
}
}

View File

@ -1,33 +0,0 @@
const { Component } = require('react')
const h = require('react-hyperscript')
const PropTypes = require('prop-types')
const classnames = require('classnames')
class TabBar extends Component {
render () {
const { tabs = [], onSelect, isActive } = this.props
return (
h('.tab-bar', {}, [
tabs.map(({ key, content }) => {
return h('div', {
className: classnames('tab-bar__tab pointer', {
'tab-bar__tab--active': isActive(key, content),
}),
onClick: () => onSelect(key),
key,
}, content)
}),
h('div.tab-bar__tab.tab-bar__grow-tab'),
])
)
}
}
TabBar.propTypes = {
isActive: PropTypes.func.isRequired,
tabs: PropTypes.array,
onSelect: PropTypes.func,
}
module.exports = TabBar

View File

@ -1,160 +0,0 @@
const Component = require('react').Component
const h = require('react-hyperscript')
const inherits = require('util').inherits
const connect = require('react-redux').connect
const Identicon = require('./identicon')
const ethNetProps = require('eth-net-props')
const selectors = require('../selectors')
const actions = require('../actions')
const { conversionUtil, multiplyCurrencies } = require('../conversion-util')
const TokenMenuDropdown = require('./dropdowns/token-menu-dropdown.js')
function mapStateToProps (state) {
return {
network: state.metamask.network,
currentCurrency: state.metamask.currentCurrency,
selectedTokenAddress: state.metamask.selectedTokenAddress,
userAddress: selectors.getSelectedAddress(state),
contractExchangeRates: state.metamask.contractExchangeRates,
conversionRate: state.metamask.conversionRate,
sidebarOpen: state.appState.sidebar.isOpen,
}
}
function mapDispatchToProps (dispatch) {
return {
setSelectedToken: address => dispatch(actions.setSelectedToken(address)),
hideSidebar: () => dispatch(actions.hideSidebar()),
}
}
module.exports = connect(mapStateToProps, mapDispatchToProps)(TokenCell)
inherits(TokenCell, Component)
function TokenCell () {
Component.call(this)
this.state = {
tokenMenuOpen: false,
}
}
TokenCell.prototype.render = function () {
const { tokenMenuOpen } = this.state
const props = this.props
const {
address,
symbol,
string,
network,
setSelectedToken,
selectedTokenAddress,
contractExchangeRates,
conversionRate,
hideSidebar,
sidebarOpen,
currentCurrency,
// userAddress,
image,
} = props
let currentTokenToFiatRate
let currentTokenInFiat
let formattedFiat = ''
if (contractExchangeRates[address]) {
currentTokenToFiatRate = multiplyCurrencies(
contractExchangeRates[address],
conversionRate
)
currentTokenInFiat = conversionUtil(string, {
fromNumericBase: 'dec',
fromCurrency: symbol,
toCurrency: currentCurrency.toUpperCase(),
numberOfDecimals: 2,
conversionRate: currentTokenToFiatRate,
})
formattedFiat = currentTokenInFiat.toString() === '0'
? ''
: `${currentTokenInFiat} ${currentCurrency.toUpperCase()}`
}
const showFiat = Boolean(currentTokenInFiat) && currentCurrency.toUpperCase() !== symbol
return (
h('div.token-list-item', {
className: `token-list-item ${selectedTokenAddress === address ? 'token-list-item--active' : ''}`,
// style: { cursor: network === '1' ? 'pointer' : 'default' },
// onClick: this.view.bind(this, address, userAddress, network),
onClick: () => {
setSelectedToken(address)
selectedTokenAddress !== address && sidebarOpen && hideSidebar()
},
}, [
h(Identicon, {
className: 'token-list-item__identicon',
diameter: 50,
address,
network,
image,
}),
h('div.token-list-item__balance-ellipsis', null, [
h('div.token-list-item__balance-wrapper', null, [
h('div.token-list-item__token-balance', `${string || 0}`),
h('div.token-list-item__token-symbol', symbol),
showFiat && h('div.token-list-item__fiat-amount', {
style: {},
}, formattedFiat),
]),
h('i.fa.fa-ellipsis-h.fa-lg.token-list-item__ellipsis.cursor-pointer', {
onClick: (e) => {
e.stopPropagation()
this.setState({ tokenMenuOpen: true })
},
}),
]),
tokenMenuOpen && h(TokenMenuDropdown, {
onClose: () => this.setState({ tokenMenuOpen: false }),
token: { symbol, address },
}),
/*
h('button', {
onClick: this.send.bind(this, address),
}, 'SEND'),
*/
])
)
}
TokenCell.prototype.send = function (address, event) {
event.preventDefault()
event.stopPropagation()
const url = tokenFactoryFor(address)
if (url) {
navigateTo(url)
}
}
TokenCell.prototype.view = function (address, userAddress, network, event) {
const url = ethNetProps.explorerLinks.getExplorerTokenLinkFor(address, userAddress, network)
if (url) {
navigateTo(url)
}
}
function navigateTo (url) {
global.platform.openWindow({ url })
}
function tokenFactoryFor (tokenAddress) {
return `https://tokenfactory.surge.sh/#/token/${tokenAddress}`
}

View File

@ -1,188 +0,0 @@
const Component = require('react').Component
const PropTypes = require('prop-types')
const h = require('react-hyperscript')
const inherits = require('util').inherits
const TokenTracker = require('eth-token-watcher')
const TokenCell = require('./token-cell.js')
const connect = require('react-redux').connect
const selectors = require('../selectors')
const log = require('loglevel')
function mapStateToProps (state) {
return {
network: state.metamask.network,
tokens: state.metamask.tokens,
userAddress: selectors.getSelectedAddress(state),
assetImages: state.metamask.assetImages,
}
}
const defaultTokens = []
const contracts = require('eth-contract-metadata')
for (const address in contracts) {
const contract = contracts[address]
if (contract.erc20) {
contract.address = address
defaultTokens.push(contract)
}
}
TokenList.contextTypes = {
t: PropTypes.func,
}
module.exports = connect(mapStateToProps)(TokenList)
inherits(TokenList, Component)
function TokenList () {
this.state = {
tokens: [],
isLoading: true,
network: null,
}
Component.call(this)
}
TokenList.prototype.render = function () {
const { userAddress, assetImages } = this.props
const state = this.state
const { tokens, isLoading, error } = state
if (isLoading) {
return this.message(this.context.t('loadingTokens'))
}
if (error) {
log.error(error)
return h('.hotFix', {
style: {
padding: '80px',
},
}, [
this.context.t('troubleTokenBalances'),
h('span.hotFix', {
style: {
color: 'rgba(247, 134, 28, 1)',
cursor: 'pointer',
},
onClick: () => {
global.platform.openWindow({
url: `https://ethplorer.io/address/${userAddress}`,
})
},
}, this.context.t('here')),
])
}
return h('div', tokens.map((tokenData) => {
tokenData.image = assetImages[tokenData.address]
return h(TokenCell, tokenData)
}))
}
TokenList.prototype.message = function (body) {
return h('div', {
style: {
display: 'flex',
height: '250px',
alignItems: 'center',
justifyContent: 'center',
padding: '30px',
},
}, body)
}
TokenList.prototype.componentDidMount = function () {
this.createFreshTokenTracker()
}
TokenList.prototype.createFreshTokenTracker = function () {
if (this.tracker) {
// Clean up old trackers when refreshing:
this.tracker.stop()
this.tracker.removeListener('update', this.balanceUpdater)
this.tracker.removeListener('error', this.showError)
}
if (!global.ethereumProvider) return
const { userAddress } = this.props
this.tracker = new TokenTracker({
userAddress,
provider: global.ethereumProvider,
tokens: this.props.tokens,
pollingInterval: 8000,
})
// Set up listener instances for cleaning up
this.balanceUpdater = this.updateBalances.bind(this)
this.showError = (error) => {
this.setState({ error, isLoading: false })
}
this.tracker.on('update', this.balanceUpdater)
this.tracker.on('error', this.showError)
this.tracker.updateBalances()
.then(() => {
this.updateBalances(this.tracker.serialize())
})
.catch((reason) => {
log.error(`Problem updating balances`, reason)
this.setState({ isLoading: false })
})
}
TokenList.prototype.componentDidUpdate = function (nextProps) {
const {
network: oldNet,
userAddress: oldAddress,
tokens,
} = this.props
const {
network: newNet,
userAddress: newAddress,
tokens: newTokens,
} = nextProps
const isLoading = newNet === 'loading'
const missingInfo = !oldNet || !newNet || !oldAddress || !newAddress
const sameUserAndNetwork = oldAddress === newAddress && oldNet === newNet
const shouldUpdateTokens = isLoading || missingInfo || sameUserAndNetwork
const oldTokensLength = tokens ? tokens.length : 0
const tokensLengthUnchanged = oldTokensLength === newTokens.length
if (tokensLengthUnchanged && shouldUpdateTokens) return
this.setState({ isLoading: true })
this.createFreshTokenTracker()
}
TokenList.prototype.updateBalances = function (tokens) {
if (!this.tracker.running) {
return
}
this.setState({ tokens, isLoading: false })
}
TokenList.prototype.componentWillUnmount = function () {
if (!this.tracker) return
this.tracker.stop()
this.tracker.removeListener('update', this.balanceUpdater)
this.tracker.removeListener('error', this.showError)
}
// function uniqueMergeTokens (tokensA, tokensB = []) {
// const uniqueAddresses = []
// const result = []
// tokensA.concat(tokensB).forEach((token) => {
// const normal = normalizeAddress(token.address)
// if (!uniqueAddresses.includes(normal)) {
// uniqueAddresses.push(normal)
// result.push(token)
// }
// })
// return result
// }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 289 KiB

View File

@ -1,26 +0,0 @@
const fs = require('fs')
const path = require('path')
module.exports = bundleCss
var cssFiles = {
'index.css': fs.readFileSync(path.join(__dirname, '/app/css/output/index.css'), 'utf8'),
'first-time.css': fs.readFileSync(path.join(__dirname, '../mascara/src/app/first-time/index.css'), 'utf8'),
// 'react-tooltip.css': fs.readFileSync(path.join(__dirname, '..', 'node_modules', 'react-tooltip', 'dist', 'style.css'), 'utf8'),
'react-css': fs.readFileSync(path.join(__dirname, '..', 'node_modules', 'react-select', 'dist', 'react-select.css'), 'utf8'),
}
function bundleCss () {
var cssBundle = Object.keys(cssFiles).reduce(function (bundle, fileName) {
var fileContent = cssFiles[fileName]
var output = String()
output += '/*========== ' + fileName + ' ==========*/\n\n'
output += fileContent
output += '\n\n'
return bundle + output
}, String())
return cssBundle
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 285 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 210 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 357 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 292 KiB