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

107 lines
3.3 KiB
Text
Raw Normal View History

import _ from 'underscore';
import request from 'request';
import NylasStore from 'nylas-store';
import {FocusedContactsStore} from 'nylas-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.
class GithubUserStore extends NylasStore {
constructor() {
super();
this._profile = null;
this._cache = {};
this._loading = false;
this._error = null;
// Register a callback with the FocusedContactsStore. This will tell us
// whenever the selected person has changed so we can refresh our data.
this.listenTo(FocusedContactsStore, this._onFocusedContactChanged);
}
// Getter Methods
profileForFocusedContact() {
return this._profile;
}
loading() {
return this._loading;
}
error() {
return this._error;
}
// Called when the FocusedContactStore `triggers`, notifying us that the data
// it vends has changed.
_onFocusedContactChanged = ()=> {
// Grab the new focused contact
const 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.
this._error = null;
this._profile = null;
if (contact) {
this._profile = this._cache[contact.email];
if (this._profile === undefined) {
// Make a Github search request to find the matching user profile
this._githubFetchProfile(contact.email);
}
}
this.trigger(this);
}
_githubFetchProfile(email) {
this._loading = true
this._githubRequest(`https://api.github.com/search/users?q=${email}`, (err, resp, data)=> {
if (err || !data) {
return;
}
if (data.message !== undefined) {
console.warn(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.
let profile = false;
if (data && data.items && data.items[0]) {
profile = data.items[0];
}
// If a profile was found, make a second request for the user's public
// repositories.
if (profile !== false) {
profile.repos = [];
this._githubRequest(profile.repos_url, (reposErr, reposResp, 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.
this.trigger(this);
});
}
this._loading = false;
this._profile = this._cache[email] = profile;
this.trigger(this);
});
}
// 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) {
return request({url: url, headers: {'User-Agent': 'request'}, json: true}, callback);
}
}
export default new GithubUserStore();