Skip to content

Commit

Permalink
Start working on Docco (run npm i)
Browse files Browse the repository at this point in the history
  • Loading branch information
vrde committed Nov 2, 2016
1 parent 72d9f70 commit 87b6550
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 43 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -14,5 +14,6 @@

build/*
dist/*
docs/*

node_modules/*
8 changes: 8 additions & 0 deletions build-docs.sh
@@ -0,0 +1,8 @@
#!/usr/bin/env bash

ROOT=./src
for DIR in `find $ROOT -type d`; do
INDIR=$DIR/*
OUTDIR=docs${DIR:${#ROOT}};
./node_modules/.bin/docco $INDIR -o $OUTDIR
done;
29 changes: 0 additions & 29 deletions docs/bootstraprc

This file was deleted.

4 changes: 3 additions & 1 deletion package.json
Expand Up @@ -19,7 +19,8 @@
"build:dist": "./pack-extension.sh || true",
"clean": "rimraf ./build ./dist",
"test": "mocha --compilers js:babel-register --reporter spec",
"test:watch": "mocha -w --compilers js:babel-register --reporter spec"
"test:watch": "mocha -w --compilers js:babel-register --reporter spec",
"docs": "rimraf ./docs && ./build-docs.sh"
},
"devDependencies": {
"autoprefixer": "^6.4.0",
Expand All @@ -40,6 +41,7 @@
"chai": "^3.5.0",
"cross-env": "^2.0.0",
"css-loader": "^0.23.1",
"docco": "^0.7.0",
"dotenv": "^2.0.0",
"eslint": "^3.3.1",
"eslint-config-ascribe-react": "^1.4.0",
Expand Down
65 changes: 62 additions & 3 deletions src/app.js
@@ -1,15 +1,38 @@
// Install any necessary polyfills into global, such as es6, stage/3, stage/4, etc. as needed
// # Welcome to the extension docs!
// Here you can learn how the extension works and, if this is what you aim for,
// where to put your hands to hack the code.
//
// ## Structure of the extension
// The extension has two parts:
// - a content script
// - event pages.
//
// The **content script** is the JavaScript code injected into the Facebook.com
// website. It can interact with the elements in the page to scrape the data and
// prepare the payload to be sent to the API.
//
// On the other side there are **event pages**. They are scripts triggered by
// some events sent from the **content script**. Since they run in *browser-space*,
// they have the permission (if granted) to do cross-domain requests, access
// cookies, and [much more](https://developer.chrome.com/extensions/declare_permissions).
// All **event pages** are contained in the [`./background`](./background/app.html) folder.
// (the name is **background** for historical reasons and it might be subject of changes
// in the future).

// # Code
// Import the styles for the app.
require('../styles/app.scss');

// Install any necessary polyfills into global, such as es6, stage/3, stage/4, etc. as needed
import 'core-js/es6';

// Import the react toolkit.
// Seems like importing 'react-dom' is not enough, we need to import 'react' as well.
import React from 'react';
import ReactDOM from 'react-dom';
import ReactDOMServer from 'react-dom/server';

// import nacl from 'tweetnacl';
// Import other utils to handle the DOM and scrape data.
import uuid from 'uuid';
import $ from 'jquery';
import 'arrive';
Expand All @@ -23,16 +46,25 @@ import { registerHandlers } from './handlers/index';
import StartButton from './components/startButton';
import OnboardingBox from './components/onboardingBox';

// Boot the user script. This is the first function called.
// Everything starts from here.
function boot () {
console.log(`Fbtrex version ${config.VERSION} build ${config.BUILD} loading.`);

// Source handlers so they can process events
// Register all the event handlers.
// An event handler is a piece of code responsible for a specific task.
// You can learn more in the [`./handlers`](./handlers/index.html) directory.
registerHandlers(hub);

// Lookup the current user and decide what to do.
userLookup(response => {
// `response` contains the user's public key and its status,
// if the key has just been created, the status is `new`.
if (response.status === 'new') {
// In the case the status is `new` then we need to onboard the user.
onboarding(response.publicKey);
} else {
// Otherwise, we load all the components of the UI and the watchers.
render();
timeline();
prefeed();
Expand All @@ -42,10 +74,18 @@ function boot () {
});
}

// The function `userLookup` communicates with the **action pages**
// to get information about the current user from the browser storage
// (the browser storage is unreachable from a **content script**).
function userLookup (callback) {
// Extract the data from the DOM.
const basicInfo = scrapeUserData($('body'));
// Set the `userId` in the global configuration object.
config.userId = basicInfo.id;
// Propagate the data to all the handlers interested in that event.
hub.event('user', basicInfo);
// Finally, retrieve the user from the browser storage. This is achieved
// sending a message to the `chrome.runtime`.
chrome.runtime.sendMessage({
type: 'userLookup',
payload: {
Expand Down Expand Up @@ -101,20 +141,39 @@ function processTimeline () {
hub.event('newTimeline', { uuid: uuid.v4(), dt: getTimeISO8601() });
}

// The function `onboarding` guides the user through the public key
// registration.
// The flow is the following:
// 1. display a message at the top of the page. The message includes the
// a public key and it prompts the user to copy paste it in a
// new public post.
// 2. Wait until a post appears in the timeline.
// 3. Once the post appears, extract its permalink and send it to the API.
// 4. If the API call is successful, an **activity page** will update the
// status of the key from `new` to `verified`.
function onboarding (publicKey) {
// The first action is to display the big information box.
$('#mainContainer').prepend($(ReactDOMServer.renderToString(
<OnboardingBox publicKey={publicKey} />
)));

// Then we listen to all the new posts appearing on the user's timeline.
document.arrive('#contentCol .userContentWrapper', function () {
const $elem = $(this).parent();

// Process the post only if its html contains the user's public key.
if ($elem.html().indexOf(publicKey) !== -1) {
// Extract the URL of the post.
var permalink = $elem.find('[href^="/permalink.php"]')
.attr('href');

console.log('permalink', permalink);

// Kindly ask to verify the user's public key against the API.
// Since this is a cross domain request, we need to delegate the
// call to an **action page**. If the call is successful, the action
// page handling the event will update the status of the key in the
// database.
chrome.runtime.sendMessage({
type: 'userVerify',
payload: {
Expand Down
15 changes: 7 additions & 8 deletions src/background/account.js
Expand Up @@ -38,12 +38,11 @@ function userLookup ({ userId }, sendResponse) {
};

function userVerify ({ permalink, publicKey, userId }, sendResponse) {
api
.register({ permalink, publicKey })
.catch/* 'then' */(response => {
update(userId, { status: 'verified' })
.then(response => sendResponse('ok'))
.catch(response => sendResponse('ok'/* 'error' */));
});
// .catch(response => sendResponse('error'));
api.register({ permalink, publicKey })
.catch/* 'then' */(response => {
update(userId, { status: 'verified' })
.then(response => sendResponse('ok'))
.catch(response => sendResponse('ok'/* 'error' */));
});
// .catch(response => sendResponse('error'));
};
2 changes: 1 addition & 1 deletion src/background/db.js
Expand Up @@ -9,7 +9,7 @@ export function get (key, setIfMissing) {
backend.get(key, val => {
if (chrome.runtime.lastError) {
reject(chrome.runtime.lastError);
} else if (isEmpty(val)) {
} else if (isEmpty(val) && !isEmpty(setIfMissing)) {
var newVal = isFunction(setIfMissing) ? setIfMissing(key) : setIfMissing;
backend.set(newVal, () => resolve(newVal));
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/utils.js
Expand Up @@ -27,7 +27,7 @@ export function normalizeUrl (url) {
}

export function isEmpty (object) {
return object === null || Object.keys(object).length === 0;
return object === null || object === undefined || Object.keys(object).length === 0;
}

export function isFunction (value) {
Expand Down

0 comments on commit 87b6550

Please sign in to comment.