diff --git a/package.json b/package.json index 0f369ce..83ef85d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@ezerous/breeze", - "version": "0.5.0", + "version": "0.6.0", "description": "A reactive data-store for OrbitDB.", "license": "MIT", "author": "Ezerous ", diff --git a/src/ipfs/ipfsActions.js b/src/ipfs/ipfsActions.js index 26e989e..b0857a9 100644 --- a/src/ipfs/ipfsActions.js +++ b/src/ipfs/ipfsActions.js @@ -1,3 +1,7 @@ export const IPFS_INITIALIZING = 'IPFS_INITIALIZING'; export const IPFS_INITIALIZED = 'IPFS_INITIALIZED'; export const IPFS_FAILED = 'IPFS_FAILED'; + +export const IPFS_PEER_EVENT_LISTEN = 'IPFS_PEER_EVENT_LISTEN'; +export const IPFS_PEER_CONNECTED = 'IPFS_PEER_CONNECTED'; +export const IPFS_PEER_DISCONNECTED = 'IPFS_PEER_DISCONNECTED'; diff --git a/src/ipfs/ipfsReducer.js b/src/ipfs/ipfsReducer.js index d34f69f..80833f9 100644 --- a/src/ipfs/ipfsReducer.js +++ b/src/ipfs/ipfsReducer.js @@ -1,8 +1,16 @@ -import { IPFS_INITIALIZING , IPFS_INITIALIZED, IPFS_FAILED } from "./ipfsActions"; +import { + IPFS_INITIALIZING, + IPFS_INITIALIZED, + IPFS_FAILED, + IPFS_PEER_CONNECTED, + IPFS_PEER_DISCONNECTED +} from "./ipfsActions"; import { STATUS_UNINITIALIZED, STATUS_INITIALIZING, STATUS_INITIALIZED, STATUS_FAILED } from "../constants"; const initialState = { - status: STATUS_UNINITIALIZED + status: STATUS_UNINITIALIZED, + id: null, + peers:[] }; const ipfsReducer = (state = initialState, action) => { @@ -18,13 +26,29 @@ const ipfsReducer = (state = initialState, action) => { case IPFS_INITIALIZED: return { ...state, - status: STATUS_INITIALIZED + status: STATUS_INITIALIZED, + id: action.id }; case IPFS_FAILED: return { ...state, status: STATUS_FAILED }; + case IPFS_PEER_CONNECTED: + const { peerId } = action; + const index = state.peers.findIndex(peer => peer === peerId); + if(index === -1) + return { + ...state, + peers: [...state.peers, peerId] + }; + return state; + case IPFS_PEER_DISCONNECTED: + const peerIndex = state.peers.findIndex(peer => peer === action.peerId); + return { + ...state, + peers: state.peers.filter((peer, index) => index !== peerIndex) + }; default: return state; } diff --git a/src/ipfs/ipfsSaga.js b/src/ipfs/ipfsSaga.js index 9338edc..9f6393f 100644 --- a/src/ipfs/ipfsSaga.js +++ b/src/ipfs/ipfsSaga.js @@ -1,7 +1,8 @@ -import { call, put } from 'redux-saga/effects' +import {call, put, spawn, take} from 'redux-saga/effects' import IPFS from 'ipfs'; import * as IpfsActions from "./ipfsActions"; +import {eventChannel} from "redux-saga"; const LOGGING_PREFIX = 'ipfsSaga: '; @@ -14,8 +15,12 @@ export function * initializeIPFS (ipfsOptions) { // Initialize IPFS const ipfs = yield call(IPFS.create, ipfsOptions); + const { id } = yield call(ipfs.id); - yield put({ type: IpfsActions.IPFS_INITIALIZED, ipfs }); + yield put({ type: IpfsActions.IPFS_INITIALIZED, ipfs, id }); + + // Event channel setup + yield spawn(callListenForIpfsPeerEvent, { ipfs }); return ipfs; } catch (error) { @@ -24,3 +29,41 @@ export function * initializeIPFS (ipfsOptions) { console.error(error); } } + +/* + * For peer connection/disconnection events + */ +function createIpfsPeerChannel (ipfs){ + return eventChannel(emit => { + const onPeerConnected = (peerInfo) => { + emit({ type: IpfsActions.IPFS_PEER_CONNECTED, peerId: peerInfo.remotePeer.toB58String() }); + }; + const onPeerDisconnected = (peerInfo) => { + emit({ type: IpfsActions.IPFS_PEER_DISCONNECTED, peerId: peerInfo.remotePeer.toB58String() }); + }; + + const eventListener = ipfs.libp2p.connectionManager + .on('peer:connect', onPeerConnected) + .on('peer:disconnect', onPeerDisconnected) + + return () => { + eventListener.removeListener('peer:connect',onPeerConnected) + eventListener.removeListener('peer:disconnect',onPeerDisconnected) + }; + }) +} + +function * callListenForIpfsPeerEvent ({ ipfs }) { + const ipfsPeerChannel = yield call(createIpfsPeerChannel, ipfs); + + yield put({type: IpfsActions.IPFS_PEER_EVENT_LISTEN}); + + try { + while (true) { + let event = yield take(ipfsPeerChannel); + yield put(event); + } + } finally { + ipfsPeerChannel.close(); + } +}