Skip to content
This repository has been archived by the owner on Feb 1, 2024. It is now read-only.

Add Metamask login #83

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3,503 changes: 2,365 additions & 1,138 deletions package-lock.json

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions src/components/Curtain.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react'
import PropTypes from 'prop-types'

const Curtain = ({ label }) => (
<div className="curtain">
<div className="curtainlabel">{label}</div>
</div>
)

Curtain.propTypes = {
label: PropTypes.string.isRequired
}

export default Curtain
6 changes: 3 additions & 3 deletions src/components/DropZone.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import React from 'react'
import PropTypes from 'prop-types'

import '../styles/DropZone.scss'
import '../styles/Curtain.scss'

const DropZone = props => {
const { onDrop, onDragLeave, label } = props
return (
<div
className="dropzone"
className="curtain"
onDrop={onDrop}
onDragLeave={onDragLeave}
>
<div className="droplabel">{label}</div>
<div className="curtainlabel">{label}</div>
</div>
)
}
Expand Down
20 changes: 17 additions & 3 deletions src/components/LoginForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import PropTypes from 'prop-types'
import { CSSTransitionGroup } from 'react-transition-group'
import { useTranslation } from 'react-i18next'

import metamaskLogo from '../images/metamask-fox.svg'

import '../styles/SubmitButton.scss'
import '../styles/InputField.scss'

function LoginForm ({ theme, onSubmit, setUsernameInputRef }) {
function LoginForm ({ theme, onSubmit, setUsernameInputRef, enableMetamask, metamaskEnabled }) {
const [t] = useTranslation()
const [currentLength, setCurrentLength] = useState(0)

Expand All @@ -30,7 +32,8 @@ function LoginForm ({ theme, onSubmit, setUsernameInputRef }) {
className="inputs"
transitionAppearTimeout={5000}
transitionEnterTimeout={5000}
transitionLeaveTimeout={5000}>
transitionLeaveTimeout={5000}
>
<div className="usernameRow" onClick={() => usernameInputRef.current.focus()}>
<input
ref={usernameInputRef}
Expand All @@ -46,6 +49,15 @@ function LoginForm ({ theme, onSubmit, setUsernameInputRef }) {
<span className="hint">{currentLength > 0 ? t('login.pressEnterToLogin') : null}</span>
<input type="submit" value="Connect" style={{ display: 'none' }} />
</div>
<div className="loginOptions">
<button
onClick={enableMetamask}
className={`metamaskButton${metamaskEnabled ? ' enabled' : ''}`}
>
<img src={metamaskLogo} className="metamaskLogo" />
{metamaskEnabled ? t('login.metamask.enabled') : t('login.metamask.disabled')}
</button>
</div>
</CSSTransitionGroup>
</form>
)
Expand All @@ -54,7 +66,9 @@ function LoginForm ({ theme, onSubmit, setUsernameInputRef }) {
LoginForm.propTypes = {
theme: PropTypes.object.isRequired,
onSubmit: PropTypes.func.isRequired,
setUsernameInputRef: PropTypes.func
setUsernameInputRef: PropTypes.func,
enableMetamask: PropTypes.func,
metamaskEnabled: PropTypes.bool
}

export default LoginForm
9 changes: 5 additions & 4 deletions src/components/MessageParts/MessageUser.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import createColor from '../../utils/create-color'
function MessageUser ({ message, colorify, isCommand, onClick }) {
const {
userIdentity,
meta: { from: userProfile }
meta: { from: profile }
} = message

const color =
Expand All @@ -20,9 +20,10 @@ function MessageUser ({ message, colorify, isCommand, onClick }) {
className={classNames('Message__User', { command: isCommand })}
style={{ color }}
onClick={evt => {
if (typeof onClick === 'function') onClick(evt, userProfile, userIdentity)
}}>
{userProfile ? userProfile.name : ''}
if (typeof onClick === 'function') onClick(evt, profile, userIdentity)
}}
>
{profile ? (typeof profile.name === 'string' ? profile.name : profile.name.id) : ''}
</div>
)
}
Expand Down
42 changes: 24 additions & 18 deletions src/containers/ChannelHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import { useTranslation } from 'react-i18next'
import RootStoreContext from '../context/RootStoreContext'

import ChannelLink from './ChannelLink'
import Curtain from '../components/Curtain'

import '../styles/ChannelHeader.scss'
import '../styles/Curtain.scss'

function ChannelHeader ({ match }) {
const { networkStore, uiStore } = useContext(RootStoreContext)
Expand All @@ -35,26 +37,30 @@ function ChannelHeader ({ match }) {

return (
<Observer>
{() => (
<div className="Header" onClick={onHeaderClick}>
<div className="ChannelName">
<div className="currentChannel">
{currentChannelName ? `#${currentChannelName}` : overrideName}
{() =>
networkStore.isOnline ? (
<div className="Header" onClick={onHeaderClick}>
<div className="ChannelName">
<div className="currentChannel">
{currentChannelName ? `#${currentChannelName}` : overrideName}
</div>
{networkStore.channelsAsArray
.filter(c => c.channelName !== currentChannelName)
.sort((a, b) => a.channelName.localeCompare(b.channelName))
.map(c => (
<ChannelLink
key={c.channelName}
channel={c}
theme={{ ...uiStore.theme }}
onClick={onChannelClick}
/>
))}
</div>
{networkStore.channelsAsArray
.filter(c => c.channelName !== currentChannelName)
.sort((a, b) => a.channelName.localeCompare(b.channelName))
.map(c => (
<ChannelLink
key={c.channelName}
channel={c}
theme={{ ...uiStore.theme }}
onClick={onChannelClick}
/>
))}
</div>
</div>
)}
) : (
<Curtain label={t('login.metamask.info')} />
)
}
</Observer>
)
}
Expand Down
14 changes: 11 additions & 3 deletions src/containers/MessageUserProfilePanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ function MessageUserProfilePanel () {
uiStore.userProfilePanelIsOpen ? (
<div
className="MessageUserProfilePanel"
style={calculatePanelStyle(uiStore.userProfilePanelPosition, uiStore.windowDimensions)}>
style={calculatePanelStyle(uiStore.userProfilePanelPosition, uiStore.windowDimensions)}
>
<BackgroundAnimation
style={{ top: '-30px', left: '-70px', zIndex: '-1', display: 'block' }}
size={256}
Expand Down Expand Up @@ -62,10 +63,17 @@ function renderUserCard (t, user) {
component="div"
transitionAppearTimeout={1500}
transitionEnterTimeout={0}
transitionLeaveTimeout={0}>
transitionLeaveTimeout={0}
>
<img className="picture" src={earthImg} />
</CSSTransitionGroup>
<div className="name">{user.profile.name}</div>
<div className="name">
{user.profile.name
? typeof user.profile.name === 'string'
? user.profile.name
: user.profile.name.id
: ''}
</div>
<div className="country">{country ? country + ', Earth' : 'Earth'}</div>
<dl className="profileDataContainer">
<dt>{t('userProfile.identityType')}:</dt>
Expand Down
54 changes: 54 additions & 0 deletions src/images/metamask-fox.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 7 additions & 1 deletion src/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,15 @@
"login": {
"nickname": "Nickname",
"orLoginWith": "Or login with",
"pressEnterToLogin": "Press ENTER to login"
"pressEnterToLogin": "Press ENTER to login",
"metamask": {
"disabled": "Log in with Metamask",
"enabled": "Metamask Connected",
"info": "Connect the created OrbitDB account to your Ethereum address by signing the message."
}
},
"loading": "Loading",
"or": "or",
"settings": {
"names": {
"themeName": "Theme",
Expand Down
10 changes: 8 additions & 2 deletions src/locales/fi/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
},
"disclaimer": {
"alpha": {
"content": "Tämä on ohjelman alpha versio. Asiat muuttuvat ja menevät rikki \u2014 keskustelut häviävät. Käytä omalla vastuulla."
"content": "Tämä on ohjelman alpha-versio. Asiat muuttuvat ja menevät rikki \u2014 keskustelut häviävät. Käytä omalla vastuulla."
}
},
"joinChannel": {
Expand All @@ -35,9 +35,15 @@
"login": {
"nickname": "Nimimerkki",
"orLoginWith": "Tai kirjaudu käyttäen",
"pressEnterToLogin": "Paina ENTER kirjautuaksesi"
"pressEnterToLogin": "Paina ENTER kirjautuaksesi",
"metamask": {
"disabled": "Kirjaudu sisään Metamaskilla",
"enabled": "Sulje Metamask-yhteys",
"info": "Liitä luotu OrbitDB-tunnus Ethereum-tiliisi allekirjoittamalla viesti."
}
},
"loading": "Ladataan",
"or": "tai",
"settings": {
"names": {
"themeName": "Teema",
Expand Down
15 changes: 12 additions & 3 deletions src/stores/ChannelStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,17 +179,26 @@ export default class ChannelStore {
sendNotification (entry) {
const {
sessionStore: {
rootStore: { uiStore: currentChannelName }
rootStore: {
uiStore: { currentChannelName }
}
}
} = this.network
const payload = entry.payload.value

const {
content,
meta: {
from: { name }
}
} = entry.payload.value

if (document.hidden || this.channelName !== currentChannelName) {
if (this.unreadMessages.length > 1) {
notify(`${this.unreadMessages.length} unread messages in #${this.channelName}`, '')
} else {
notify(
`New message in #${this.channelName}`,
`${payload.meta.from.name}: ${payload.content}`
`${typeof name === 'string' ? name : name.id}: ${content}`
)
}
}
Expand Down
14 changes: 13 additions & 1 deletion src/stores/OrbitStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,27 @@ export default class OrbitStore {

return new Promise(resolve => {
const settings = this.settingsStore.networkSettings.orbit

const options = {
dbOptions: {
directory: `${settings.root}/data/orbit-db`
},
channelOptions: {}
}

const node = new Orbit(ipfs, options)

node.events.once('connected', () => this.onStarted(node, resolve))
node.connect(this.sessionStore.username)

const credentials = this.sessionStore.metamask
? {
type: 'purser-metamask',
username: this.sessionStore.username,
provider: this.sessionStore.metamask
}
: this.sessionStore.username

node.connect(credentials)
})
}

Expand Down
Loading