Mailspring/internal_packages/github-contact-card/lib/github-user-store.coffee

84 lines
2.8 KiB
CoffeeScript

_ = require 'underscore'
Reflux = require 'reflux'
request = require 'request'
{FocusedContactsStore} = require 'nylas-exports'
module.exports =
# This package uses the Flux pattern - our Store is a small singleton that
# observes other parts of the application and vends data to our React
# component. If the user could interact with the GithubSidebar, this store
# would also listen for `Actions` emitted by our React components.
GithubUserStore = Reflux.createStore
init: ->
@_profile = null
@_cache = {}
@_loading = false
@_error = null
# Register a callback with the FocusedContactsStore. This will tell us
# whenever the selected person has changed so we can refresh our data.
@listenTo FocusedContactsStore, @_onFocusedContactChanged
# Getter Methods
profileForFocusedContact: ->
@_profile
loading: ->
@_loading
error: ->
@_error
# Called when the FocusedContactStore `triggers`, notifying us that the data
# it vends has changed.
_onFocusedContactChanged: ->
# Grab the new focused contact
contact = FocusedContactsStore.focusedContact()
# First, clear the contact that we're currently showing and `trigger`. Since
# our React component observes our store, `trigger` causes our React component
# to re-render.
@_error = null
@_profile = null
if contact
@_profile = @_cache[contact.email]
# Make a Github search request to find the matching user profile
@_githubFetchProfile(contact.email) unless @_profile?
@trigger(@)
_githubFetchProfile: (email) ->
@_loading = true
@_githubRequest "https://api.github.com/search/users?q=#{email}", (err, resp, data) =>
return if err or not data
console.warn(data.message) if data.message?
# Sometimes we get rate limit errors, etc., so we need to check and make
# sure we've gotten items before pulling the first one.
profile = data?.items?[0] ? false
# If a profile was found, make a second request for the user's public
# repositories.
if profile
profile.repos = []
@_githubRequest profile.repos_url, (err, resp, repos) =>
# Sort the repositories by their stars (`-` for descending order)
profile.repos = _.sortBy repos, (repo) -> -repo.stargazers_count
# Trigger so that our React components refresh their state and display
# the updated data.
@trigger(@)
@_loading = false
@_profile = @_cache[email] = profile
@trigger(@)
# Wrap the Node `request` library and pass the User-Agent header, which is required
# by Github's API. Also pass `json:true`, which causes responses to be automatically
# parsed.
_githubRequest: (url, callback) ->
request({url: url, headers: {'User-Agent': 'request'}, json: true}, callback)