{Utils, React, ReactDOM, Actions, RegExpUtils, IdentityStore, AccountStore, EdgehillAPI} = require 'nylas-exports' {RetinaImg} = require 'nylas-component-kit' EmailPopover = require './email-popover' PGPKeyStore = require './pgp-key-store' KeybaseUser = require '../lib/keybase-user' Identity = require './identity' kb = require './keybase' _ = require 'underscore' class KeybaseInviteButton extends React.Component constructor: (@props) -> @state = { loading: false, } _onGetKeybaseInvite: => @setState({loading: true}) token = AccountStore.tokenForAccountId(AccountStore.accounts()[0].id) errorHandler = (err) => @setState({loading: false}) NylasEnv.showErrorDialog(err.message) EdgehillAPI.makeRequest auth: user: token pass: "" path: "/keybase-invite", method: "POST", body: n1_id: IdentityStore.identityId(), error: errorHandler, success: (body, response) => @setState({loading: false}) try if not (body instanceof Object) or not body.invite_url throw new Error("We were unable to retrieve an invitation.") catch err errorHandler(err) require('electron').shell.openExternal(body.invite_url) render: => if @state.loading Processing... else We've got an invite for you! module.exports = class KeybaseSearch extends React.Component @displayName: 'KeybaseSearch' @propTypes: initialSearch: React.PropTypes.string # importFunc: a alternate function to execute when the "import" button is # clicked instead of the "please specify an email" popover importFunc: React.PropTypes.function # TODO consider just passing in a pre-specified email instead of a func? inPreferences: React.PropTypes.bool @defaultProps: initialSearch: "" importFunc: false inPreferences: false constructor: (props) -> super(props) @state = { query: props.initialSearch results: [] loading: false searchedByEmail: false } @debouncedSearch = _.debounce(@_search, 300) componentDidMount: -> @_search() componentWillReceiveProps: (props) -> @setState({query: props.initialSearch}) _search: -> oldquery = @state.query if @state.query != "" and @state.loading == false @setState({loading: true}) kb.autocomplete(@state.query, (error, profiles) => if profiles? profiles = _.map(profiles, (profile) -> return new Identity({keybase_profile: profile, isPriv: false}) ) @setState({results: profiles, loading: false}) else @setState({results: [], loading: false}) if @state.query != oldquery @debouncedSearch() ) else # no query - empty out the results @setState({results: []}) _importKey: (profile, event) => # opens a popover requesting user to enter 1+ emails to associate with a # key - a button in the popover then calls _save to actually import the key popoverTarget = event.target.getBoundingClientRect() Actions.openPopover( , {originRect: popoverTarget, direction: 'left'} ) _popoverDone: (addresses, identity) => if addresses.length < 1 # no email addresses added, noop return else identity.addresses = addresses # TODO validate the addresses? @_save(identity) _save: (identity) => # save/import a key from keybase keybaseUsername = identity.keybase_profile.components.username.val kb.getKey(keybaseUsername, (error, key) => if error console.error error else PGPKeyStore.saveNewKey(identity, key) ) _queryChange: (event) => emailQuery = RegExpUtils.emailRegex().test(event.target.value) @setState({query: event.target.value, searchedByEmail: emailQuery}) @debouncedSearch() render: -> profiles = _.map(@state.results, (profile) => # allow for overriding the import function if typeof @props.importFunc is "function" boundFunc = @props.importFunc else boundFunc = @_importKey saveButton = ( ) # TODO improved deduping? tricky because of the kbprofile - email association if not profile.keyPath? return ) if not profiles? or profiles.length < 1 profiles = [] badSearch = null loading = null empty = null if profiles.length < 1 and @state.searchedByEmail badSearch = Keybase cannot be searched by email address.
Try entering a name, or a username from GitHub, Keybase or Twitter.
if @state.loading loading = if @props.inPreferences and not loading and not badSearch and profiles.length is 0 empty =

Not a Keybase user yet?

{empty}
{ loading }
{ profiles } { badSearch }