UNPKG

react-native-studia

Version:
819 lines (661 loc) 29.7 kB
// @flow 'use strict' import { State, type ErrorCodeMessageMapping, Subscription, StudiaManagerOptions, Carriers, Network, Socket, type Subscriber, type ObservableId, type ServalId, PeerState, Feed } from './Types'; import { NetworkModule, IdentityModule, EventEmitter } from './StudiaModules'; import type { NativeIdentity, NativeFeed, NativePeer, NativeMessage } from './StudiaModules' import { parseError, ErrorCodeMessage, StudiaError, ErrorCode } from './StudiaError'; import { Identity } from './Identity' import { Peer } from './Peer' import { MyFeed } from './MyFeed' import { Message } from './Message' import { Carrier } from './Carrier' export class StudiaManager { _uniqueId: number _activePromises: { [id: string]: (error: StudiaError) => void } _errorCodesToMessagesMapping: ErrorCodeMessageMapping _eventEmitter: EventEmitter _activeSubscriptions: { [id: string]: Subscription } _activeSockets: { [id: string]: Socket<any> } carrier: Carrier constructor(options: StudiaManagerOptions = {}) { this._eventEmitter = new EventEmitter(NetworkModule) this._uniqueId = 0 this._activePromises = {} this._activeSubscriptions = {} this._activeSockets = {} this._errorCodesToMessagesMapping = options.errorCodesToMessagesMapping ? options.errorCodesToMessagesMapping : ErrorCodeMessage this.carrier = new Carrier(this) } _destroyPromises() { const destroyedError = new StudiaError( { errorCode: ErrorCode.StudiaManagerDestroyed, //reason: (null : ?string), }, this._errorCodesToMessagesMapping ) for (const id in this._activePromises) { this._activePromises[id](destroyedError) } } _destroySubscriptions() { for (const id in this._activeSubscriptions) { this._activeSubscriptions[id].remove() } } destroy() { this._destroySubscriptions() this._destroyPromises() } _nextUniqueID(): string { this._uniqueId += 1 return this._uniqueId.toString() } async _callPromise<T>(promise: Promise<T>): Promise<T> { const id = this._nextUniqueID() try { const destroyPromise = new Promise((resolve, reject) => { this._activePromises[id] = reject }) const value = await Promise.race([destroyPromise, promise]) delete this._activePromises[id] return value } catch (error) { delete this._activePromises[id] throw parseError(error.message, this._errorCodesToMessagesMapping) } } _stopObserving(observerId: ObservableId) { IdentityModule.stopObserving(observerId) } async enable(carrier: $Values<typeof Carriers>) : Promise<Network> { switch(carrier) { case Carriers.Ble: return await this._callPromise(NetworkModule.setBleEnable()); case Carriers.Wifi: return await this._callPromise(NetworkModule.setWifiEnable()); case Carriers.Hotspot: return await this._callPromise(NetworkModule.setHotspotEnable()); default: return await this._callPromise(NetworkModule.setWifiDirectEnable()); } } async disable(carrier: $Values<typeof Carriers>) : Promise<void> { switch(carrier) { case Carriers.Ble: return await this._callPromise(NetworkModule.setBleDisable()); case Carriers.Wifi: return await this._callPromise(NetworkModule.setWifiDisable()); case Carriers.Hotspot: return await this._callPromise(NetworkModule.setHotspotDisable()); default: return await this._callPromise(NetworkModule.setWifiDirectDisable()); } } state(carrier: $Values<typeof Carriers>) : Promise<$Values<typeof State>> { return this._callPromise(NetworkModule.getState(carrier)); } async createIdentity(identityName: string) : Promise<Identity> { const nativeIdentity = await this._callPromise(IdentityModule.createIdentity(identityName)) return new Identity(nativeIdentity, this) } async getIdentities() : Promise<Array<Identity>> { const nativeIdentities = await this._callPromise(IdentityModule.getIdentities()) return nativeIdentities.map((nativeIdentity: NativeIdentity) => { return new Identity(nativeIdentity, this) }) } async updateIdentity(identityKey: Subscriber, identityName: string) : Promise<Identity> { const nativeIdentity = await this._callPromise(IdentityModule.updateIdentity(identityKey, identityName)) return new Identity(nativeIdentity, this) } getFeedSocket(identityId: Subscriber, callback: (error: ?StudiaError) => void): Socket<MyFeed> { const socketId = this._nextUniqueID() var socket: Socket<MyFeed> this._callPromise(IdentityModule.runFeedObservable(identityId)) .catch((error: StudiaError) => { callback(error) }) socket = { send: async (message) => { const nativeFeed = await this._callPromise(IdentityModule.sendFeed(message)) return new MyFeed(nativeFeed, this) }, stop: () => { if(this._activeSockets[socketId] != null) { delete this._activeSockets[socketId] IdentityModule.stopFeedObservable() } } } this._activeSockets[socketId] = socket return socket } getFeeds(identityId: Subscriber, callback: (error: ?StudiaError, feeds: ?Array<MyFeed>) => void) : Subscription { const subscriptionId = this._nextUniqueID() var subscription : Subscription this._callPromise(IdentityModule.getFeeds(identityId, subscriptionId)) .then((feeds) => { const jsFeeds = feeds.map((nativeFeed: NativeFeed) => { return new MyFeed(nativeFeed, this) }) callback(null, jsFeeds) }, (error: StudiaError) => { callback(error, null) }) subscription = { remove: () => { if (this._activeSubscriptions[subscriptionId] != null) { delete this._activeSubscriptions[subscriptionId] this._stopObserving(subscriptionId) } } } this._activeSubscriptions[subscriptionId] = subscription return subscription } getContacts(identityId: Subscriber, callback: (error: ?StudiaError, peers: ?Array<Peer>) => void) : Subscription { const subscriptionId = this._nextUniqueID() var subscription : Subscription this._callPromise(IdentityModule.getContacts(identityId, subscriptionId)) .then((peers) => { const jsPeers = peers.map((nativePeer: NativePeer) => { return new Peer(nativePeer, this) }) callback(null, jsPeers) }, (error: StudiaError) => { callback(error, null) }) subscription = { remove: () => { if (this._activeSubscriptions[subscriptionId] != null) { delete this._activeSubscriptions[subscriptionId] this._stopObserving(subscriptionId) } } } this._activeSubscriptions[subscriptionId] = subscription return subscription } getBlocklist(identityId: Subscriber, callback: (error: ?StudiaError, peers: ?Array<Peer>) => void) : Subscription { const subscriptionId = this._nextUniqueID() var subscription : Subscription this._callPromise(IdentityModule.getBlocklist(identityId, subscriptionId)) .then((peers) => { const jsPeers = peers.map((nativePeer: NativePeer) => { return new Peer(nativePeer, this) }) callback(null, jsPeers) }, (error: StudiaError) => { callback(error, null) }) subscription = { remove: () => { if (this._activeSubscriptions[subscriptionId] != null) { delete this._activeSubscriptions[subscriptionId] this._stopObserving(subscriptionId) } } } this._activeSubscriptions[subscriptionId] = subscription return subscription } // getPeers(identityId: Subscriber, callback: (error: ?StudiaError, peers: ?Array<Peer>) => void) : Subscription { // const subscriptionId = this._nextUniqueID() // var subscription : Subscription // this._callPromise(IdentityModule.getPeers(identityId, subscriptionId)) // .then((peers) => { // const jsPeers = peers.map((nativePeer: NativePeer) => { // return new Peer(nativePeer, this) // }) // callback(null, jsPeers) // }, (error: StudiaError) => { // callback(error, null) // }) // subscription = { // remove: () => { // if (this._activeSubscriptions[subscriptionId] != null) { // delete this._activeSubscriptions[subscriptionId] // this._stopObserving(subscriptionId) // } // } // } // this._activeSubscriptions[subscriptionId] = subscription // return subscription // } getNearby(identityId: Subscriber, callback: (error: ?StudiaError, peers: ?Array<Peer>) => void) : Subscription { const subscriptionId = this._nextUniqueID() var subscription : Subscription this._callPromise(IdentityModule.getNearby(identityId, subscriptionId)) .then((peers) => { const jsPeers = peers.map((nativePeer: NativePeer) => { return new Peer(nativePeer, this) }) callback(null, jsPeers) }, (error: StudiaError) => { callback(error, null) }) subscription = { remove: () => { if (this._activeSubscriptions[subscriptionId] != null) { delete this._activeSubscriptions[subscriptionId] this._stopObserving(subscriptionId) } } } this._activeSubscriptions[subscriptionId] = subscription return subscription } getPeersConversations(identityId: Subscriber, callback: (error: ?StudiaError, peers: ?Array<Peer>) => void) : Subscription { const subscriptionId = this._nextUniqueID() var subscription : Subscription this._callPromise(IdentityModule.getPeersConversations(identityId, subscriptionId)) .then((peers) => { const jsPeers = peers.map((nativePeer: NativePeer) => { return new Peer(nativePeer, this) }) callback(null, jsPeers) }, (error: StudiaError) => { callback(error, null) }) subscription = { remove: () => { if (this._activeSubscriptions[subscriptionId] != null) { delete this._activeSubscriptions[subscriptionId] this._stopObserving(subscriptionId) } } } this._activeSubscriptions[subscriptionId] = subscription return subscription } getPeersRequests(identityId: Subscriber, callback: (error: ?StudiaError, peers: ?Array<Peer>) => void) : Subscription { const subscriptionId = this._nextUniqueID() var subscription : Subscription this._callPromise(IdentityModule.getPeersRequests(identityId, subscriptionId)) .then((peers) => { const jsPeers = peers.map((nativePeer: NativePeer) => { return new Peer(nativePeer, this) }) callback(null, jsPeers) }, (error: StudiaError) => { callback(error, null) }) subscription = { remove: () => { if (this._activeSubscriptions[subscriptionId] != null) { delete this._activeSubscriptions[subscriptionId] this._stopObserving(subscriptionId) } } } this._activeSubscriptions[subscriptionId] = subscription return subscription } getPeerFeeds(servalId: ServalId, callback: (error: ?StudiaError, feeds: ?Array<Feed>) => void) : Subscription { const subscriptionId = this._nextUniqueID() var subscription : Subscription this._callPromise(IdentityModule.getPeerFeeds(servalId, subscriptionId)) .then((nativeFeeds) => { callback(null, nativeFeeds) }, (error: StudiaError) => { callback(error, null) }) subscription = { remove: () => { if (this._activeSubscriptions[subscriptionId] != null) { delete this._activeSubscriptions[subscriptionId] this._stopObserving(subscriptionId) } } } this._activeSubscriptions[subscriptionId] = subscription return subscription } getPrivateMessages(identityId: Subscriber, peerId: Subscriber, callback: (error: ?StudiaError, messages: ?Array<Message>) => void) : Subscription { const subscriptionId = this._nextUniqueID() var subscription : Subscription this._callPromise(IdentityModule.getPrivateMessages(identityId, peerId, subscriptionId)) .then((messages) => { const jsMessage = messages.map((nativeMessage: NativeMessage) => { return new Message(nativeMessage, this) }) callback(null, jsMessage) }, (error: StudiaError) => { callback(error, null) }) subscription = { remove: () => { if (this._activeSubscriptions[subscriptionId] != null) { delete this._activeSubscriptions[subscriptionId] this._stopObserving(subscriptionId) } } } this._activeSubscriptions[subscriptionId] = subscription return subscription } async follow(identityId: Subscriber, peerId: Subscriber) : Promise<void> { return await this._callPromise(IdentityModule.follow(identityId, peerId)) } async block(identityId: Subscriber, peerId: Subscriber) : Promise<void> { return await this._callPromise(IdentityModule.block(identityId, peerId)) } async ignore(identityId: Subscriber, peerId: Subscriber) : Promise<void> { return await this._callPromise(IdentityModule.ignore(identityId, peerId)) } async getPeerState(identityId: Subscriber, peerId: Subscriber) : Promise<$Keys<typeof PeerState>> { return await this._callPromise(IdentityModule.getPeerState(identityId, peerId)) } // async sendMessage(identityId: Subscriber, peerId: Subscriber, message: string) : Promise<Message> { // const nativeMessage = await this._callPromise(IdentityModule.sendMessage(identityId, peerId, message)) // return new Message(nativeMessage, this) // } getMessageSocket(identityId: Subscriber, peerId: Subscriber, callback: (error: ?StudiaError) => void): Socket<Message> { const socketId = this._nextUniqueID() var socket: Socket<Message> this._callPromise(IdentityModule.runMessageObservable(identityId, peerId)) .catch((error: StudiaError) => { callback(error) }) socket = { send: async (message) => { const nativeMessage = await this._callPromise(IdentityModule.sendMessage(message)) return new Message(nativeMessage, this) }, stop: () => { if(this._activeSockets[socketId] != null) { delete this._activeSockets[socketId] IdentityModule.stopMessageObservable() } } } this._activeSockets[socketId] = socket return socket } onStateChange(carrier: $Values<typeof Carriers>, listener: (newState: $Keys<typeof State>) => void, emitCurrentState: boolean = false) : Subscription { const event = this._handleSubscriptionListener(carrier) const subscription : Subscription = this._eventEmitter.addListener(event, listener) const subscriptionId = this._nextUniqueID() if(emitCurrentState) { this.state(carrier).then((state) => { listener(state) }) } return this._handleSubscriptionState( subscription, subscriptionId ) } _handleSubscriptionListener( carrier: $Values<typeof Carriers> ) : string { switch(carrier) { case Carriers.Wifi: return NetworkModule.WifiStateChangeEvent case Carriers.WifiDirect: return NetworkModule.WifiDirectStateChangeEvent case Carriers.Ble: return NetworkModule.BleStateChangeEvent default: return NetworkModule.HotspotStateChangeEvent } } _handleSubscriptionState(subscription: Subscription, subscriptionId: string) : Subscription { var wrappedSubscription: Subscription wrappedSubscription = { remove: () => { if (this._activeSubscriptions[subscriptionId] != null) { delete this._activeSubscriptions[subscriptionId] subscription.remove() } } } this._activeSubscriptions[subscriptionId] = wrappedSubscription return wrappedSubscription } onUnreadMessagesChanged(identityId: Subscriber, listener: (count: number) => void) : Subscription { const subscription: Subscription = this._eventEmitter.addListener(IdentityModule.UnreadMessagesChanged, listener) const id = this._nextUniqueID() var wrappedSubscription: Subscription this._callPromise(IdentityModule.getUnreadMessages(identityId, id)) .then((count) => { listener(count) }) wrappedSubscription = { remove: () => { if (this._activeSubscriptions[id] != null) { delete this._activeSubscriptions[id] this._stopObserving(id) subscription.remove() } } } this._activeSubscriptions[id] = wrappedSubscription return wrappedSubscription } onRequestMessagesChanged(identityId: Subscriber, listener: (count: number) => void) : Subscription { const subscription: Subscription = this._eventEmitter.addListener(IdentityModule.RequestMessagesChanged, listener) const id = this._nextUniqueID() var wrappedSubscription: Subscription this._callPromise(IdentityModule.getRequestMessages(identityId, id)) .then((count) => { listener(count) }) wrappedSubscription = { remove: () => { if (this._activeSubscriptions[id] != null) { delete this._activeSubscriptions[id] this._stopObserving(id) subscription.remove() } } } this._activeSubscriptions[id] = wrappedSubscription return wrappedSubscription } onNearbyPeersChanged(identityId: Subscriber, listener: (count: number) => void) : Subscription { const subscription: Subscription = this._eventEmitter.addListener(IdentityModule.NearbyPeersChanged, listener) const id = this._nextUniqueID() var wrappedSubscription: Subscription this._callPromise(IdentityModule.getNearbyPeers(identityId, id)) .then((count) => { listener(count) }) wrappedSubscription = { remove: () => { if (this._activeSubscriptions[id] != null) { delete this._activeSubscriptions[id] this._stopObserving(id) subscription.remove() } } } this._activeSubscriptions[id] = wrappedSubscription return wrappedSubscription } // onFeedAdded(listener: (feed: MyFeed) => void) : Subscription { // const subscription: Subscription = this._eventEmitter.addListener(IdentityModule.FeedAddedEvent, listener) // const id = this._nextUniqueID() // var wrappedSubscription: Subscription // wrappedSubscription = { // remove: () => { // if (this._activeSubscriptions[id] != null) { // delete this._activeSubscriptions[id] // subscription.remove() // } // } // } // this._activeSubscriptions[id] = wrappedSubscription // return wrappedSubscription // } // onFeedReset(listener: (feeds: MyFeed[]) => void) : Subscription { // const subscription: Subscription = this._eventEmitter.addListener(IdentityModule.FeedResetEvent, listener) // const id = this._nextUniqueID() // var wrappedSubscription: Subscription // wrappedSubscription = { // remove: () => { // if (this._activeSubscriptions[id] != null) { // delete this._activeSubscriptions[id] // subscription.remove() // } // } // } // this._activeSubscriptions[id] = wrappedSubscription // return wrappedSubscription // } onFeedAdded(listener: (feed: Feed) => void) : Subscription { const subscription: Subscription = this._eventEmitter.addListener(IdentityModule.onFeedAddedEvent, listener) const id = this._nextUniqueID() var wrappedSubscription: Subscription wrappedSubscription = { remove: () => { if (this._activeSubscriptions[id] != null) { delete this._activeSubscriptions[id] subscription.remove() } } } this._activeSubscriptions[id] = wrappedSubscription return wrappedSubscription } // onFeedReset(listener: (feeds: Feed[]) => void) : Subscription { // const subscription: Subscription = this._eventEmitter.addListener(IdentityModule.onFeedResetEvent, listener) // const id = this._nextUniqueID() // var wrappedSubscription: Subscription // wrappedSubscription = { // remove: () => { // if (this._activeSubscriptions[id] != null) { // delete this._activeSubscriptions[id] // subscription.remove() // } // } // } // this._activeSubscriptions[id] = wrappedSubscription // return wrappedSubscription // } onPeerFound(listener: (peer: Peer) => void) : Subscription { const peerListener = (nativePeer : NativePeer) => { let peer = new Peer(nativePeer, this) listener(peer) } const subscription: Subscription = this._eventEmitter.addListener(IdentityModule.onPeerFoundEvent, peerListener) const id = this._nextUniqueID() var wrappedSubscription: Subscription wrappedSubscription = { remove: () => { if (this._activeSubscriptions[id] != null) { delete this._activeSubscriptions[id] subscription.remove() } } } this._activeSubscriptions[id] = wrappedSubscription return wrappedSubscription } onPeerUpdated(listener: (peer: Peer) => void) : Subscription { const peerListener = (nativePeer : NativePeer) => { let peer = new Peer(nativePeer, this) listener(peer) } const subscription: Subscription = this._eventEmitter.addListener(IdentityModule.onPeerUpdatedEvent, peerListener) const id = this._nextUniqueID() var wrappedSubscription: Subscription wrappedSubscription = { remove: () => { if (this._activeSubscriptions[id] != null) { delete this._activeSubscriptions[id] subscription.remove() } } } this._activeSubscriptions[id] = wrappedSubscription return wrappedSubscription } onPeerReset(listener: (peers: Array<Peer>) => void) : Subscription { const peerListener = (nativePeers : Array<NativePeer>) => { let peers = nativePeers.map((nativePeer) => {return new Peer(nativePeer, this)}) listener(peers) } const subscription: Subscription = this._eventEmitter.addListener(IdentityModule.onPeersResetEvent, peerListener) const id = this._nextUniqueID() var wrappedSubscription: Subscription wrappedSubscription = { remove: () => { if (this._activeSubscriptions[id] != null) { delete this._activeSubscriptions[id] subscription.remove() } } } this._activeSubscriptions[id] = wrappedSubscription return wrappedSubscription } onMessageReceived(listener: (message: Message) => void) : Subscription { const messageListener = (nativeMessage : NativeMessage) => { const msg = new Message(nativeMessage, this) listener(msg) } const subscription: Subscription = this._eventEmitter.addListener(IdentityModule.onMessageRecievedEvent, messageListener) const id = this._nextUniqueID() var wrappedSubscription: Subscription wrappedSubscription = { remove: () => { if (this._activeSubscriptions[id] != null) { delete this._activeSubscriptions[id] subscription.remove() } } } this._activeSubscriptions[id] = wrappedSubscription return wrappedSubscription } onMessageDelivered(listener: (message: Message) => void) : Subscription { const messageListener = (nativeMessage : NativeMessage) => { const msg = new Message(nativeMessage, this) listener(msg) } const subscription: Subscription = this._eventEmitter.addListener(IdentityModule.onMessageDeliveredEvent, messageListener) const id = this._nextUniqueID() var wrappedSubscription: Subscription wrappedSubscription = { remove: () => { if (this._activeSubscriptions[id] != null) { delete this._activeSubscriptions[id] subscription.remove() } } } this._activeSubscriptions[id] = wrappedSubscription return wrappedSubscription } }