Computer Science and Psychology? How does that work?

I have Masters’ Degrees in both Computer Science and Psychology. Weaving that fact casually into conversations is an excellent filter for finding other polymaths out there; the poor interdisciplinary souls that can’t help but wonder if exploring another topic will satisfy their endless curiosity. Another perk – and arguably more valuable – is the early priming to the value of the seams of disciplines.

It all started with my dissatisfaction with the Computer Science curriculum. After the second year, I started wondering:

“Do I really feel all that excited about the Dijkstra algorithm and balancing binary trees”?

I felt disappointed with the narrow understanding of what’s involved with producing software. Humans are running it; why aren’t we talking about them? Facebook was in its infancy; why aren’t we exploring where this is going? I decided to add the “human side” to my understanding (here are some tactical notes on how I managed to pull off 2 degrees at the same time). What did I find out?

Psychology and Computer Science really are quite similar

Psychology strives to dissect and understand the underlying principles of human thought and behavior. Computer Science aims to create the principles and algorithms for easier operation of the “thinking machines.” The only difference is that one deals with people – the other one with computers.

Am I suggesting that correlation between disciplines boils down to the similarity between humans and computers? To be honest, I haven’t seen an argument to the contrary.

  1. Behavioral Psychology assumes that when presented with a particular input, we can predict the outcome. In Computer Science, we call that a function.
  2. Sigmund Freud himself was heavily influenced by the dominant technology of the day: the steam engine. He concluded that the pressure and drive buildup could create issues in the “pipelines,” causing malfunctions. I’m sure he would be talking about algorithms were he born today.
  3. Cognitive Psychology is a newer branch, so it is already liberally borrowing concepts from Computer Science: Kahneman’s “Cognitive Resources” theory suggests that when certain cognitive resources (like memory or willpower) are taxed with too many demands, issues follow. Just the same way your Macbook freezes when you are trying to do too many things at once.
  4. Your brain evolved from a long line of less brilliant creatures. Many problematic behaviors (emotional reactions, self-sabotage, and craving sugar) can be traced to a conflict between the “lizard brain” and your conscious goals from the prefrontal cortex. In computer science, we would call this working with a legacy codebase.

The list goes on. Psychology can be better understood with a Computer Science lens and vice versa. For example, the concept of Intelligence was developed by the US Army to assess the “general aptitude” of their candidates. Psychologists to this day are not convinced the “General Intelligence” exists (It is defined as a result in the “Intelligence Test”). Extrapolating that into Computer Science, I don’t believe General Artificial Intelligence is possible because I don’t think Regular Intelligence™️ exists. 

The world wants you in a box.

Once I finished my studies, I expected to be highly valued in the job market due to my unique perspective (even more than all 20-year olds do). But employers didn’t really know what to do with me – there are no positions advertised in the overlap of computer science and psychology. On the one hand – the tech companies are searching for CS graduates, and on the other – a psychology degree can get you hired recruiting engineers for tech companies (like 30% of my classmates do).

It’s a shame because the overlap of computer science and psychology is uniquely positioned to solve a variety of connected worlds’ issues:

  • How do we ensure Social Media is helping mental health instead of hampering it?
  • How do we help people navigate the world of disproportionate leverage provided by technology?
  • How do we help find meaning, purpose, and psychological safety when the stable jobs are gone, and entire industries disappear every year?

These challenges are falling between the cracks of traditional disciplines – they are too “technical” for academic psychologists proud of their “Humanist” mindsets and too “Human” for average programmers, steeped in the precise world predictable world of math and physics.

Our most pressing problems started small but have been allowed to grow unhindered due to their transdisciplinary nature. They didn’t land in the purview of any single discipline, so we all ignored them as long as possible.

The challenges of the future are in the seams of things.

Studying computer science and psychology has primed me to understand the unique challenges of humans interacting with technology. We also need transdisciplinary experts in combinations of climate science + really anything, or technology + education. You probably don’t need formal degrees. Just start exploring.

The price of free time: programmer’s guide to helping a Non-profit

Congratulations! You have decided to help out a Non-Profit. Full of energy, and good intentions, you have embarked on a journey to use your professional skills to help a cause.

It’s a win-win: Surely, with a better website / CRM / tech, they will be able to help a few more people. You, on the other hand, will meet interesting folk, do something purposeful (as opposed to optimizing button colors at your day job), and learn a few things.

Here is what you need to know to not go insane:

The benefits of helping a Non-profit

You probably have personal reasons to help a Non-profit. Working on hard problems with friends is one of the most fulfilling things you can do with your life. If you are not working on a world-changing startup and you need a respite from the drudgery of corporate existence, a Non-Profit may be your best next bet – the purpose and mission are plentiful.

Non-profits are also a great place to meet interesting, like-minded people. Working side-by-side you can make real friends and create deeper connections, than you would build by exchanging the latest plots of TV shows over coffee at work.

But there also are powerful benefits directly translating to your career.

My entire programming journey started from helping a Non-profit – a scout team I was a part of. I made my first website in 1998, graduated to building one for dad’s business, and later launched a WordPress web agency. Now I work at WordPress.com, periodically reporting to the creator of WordPress himself. During that journey, I helped my high school, a local TEDx chapter, and a non-profit supporting remote work.

Working on projects is the best way to learn – you get to experiment with real-world problems and you get to try out different approaches and fail; building that tacit knowledge that makes one an expert.

Since you are not paid for your contributions, there is a shared understanding of what can be expected of you in a Non-Profit. You have a mandate to play a little, try out things your way, and goof off. To further boost learning, it feels more like play than work, encoding the knowledge much more effectively.

The traps

As with everything in life, the downsides are directly correlated to the upsides. Yes, in a Non-Profit, you can be a bit unpredictable and inexperienced. It does not feel like work and you get a breather from a corporate feel of a professional workplace.

But guess what – other people get to do that too. If you have just reserved a weekend to finish that signup page, and the people preparing the copy (texts) decided to be unprofessional – it suddenly becomes a problem.

The Hero’s (that’s you) Journey

Let’s assume you volunteered to create a website for your favorite Non-profit. Don’t be surprised, if the whole process goes like this:

  1. You start full of energy and ideas.
  2. The non-profit is eager to launch a new website because they have project X coming up.
    Project X is the most important thing, and the website (meaning you) is a blocker.
  3. You jump straight into work! You cannot be a blocker, right? You ramp up and are ready to implement the most important piece.
  4. The texts and promotional materials are not ready, despite previous promises.
  5. You try to work around these requirements – project X is most important, right?
  6. You get a call. It seems that the “About the Team” page is most important now.
  7. Let’s do a photoshoot for the Team!
  8. You still don’t have materials for project X, but you got 10 pages of UI corrections, including a bigger logo, different button colors, and some creative ideas about the slider.
  9. You start implementing those changes, still have no materials about project X.
  10. Wait, there are changes to the changes now. Can you revert to the old button color?
  11. Sometime, after a few weeks, we finally got the Project X page to work.
    The placeholder photos you chose are still there.
    “About the Team” page that got 3 meetings, photoshoot, and 12 hours of your time has gotten a total of 100 visitors this month.

Things to watch out in a Non-profit

The price of free time

Professional environments have learned a long time ago, that time is money. If everybody is salaried, the easiest way to turn a profit is to stop wasting people’s time. The correlation is clear and obvious.

I do realize that corporate environments waste mindblowing eons of their employees’ time. This is due to the scale. Big organisms being less nimble is a law of physics called inertia.

Non-profits, however, have a peculiar relationship with money. They are called Non-Profits. Duh! They get funded through donations, grants, and sometimes sales – but they are incentivized not to run a tight operation. Volunteers’ time is treated as free, so wastefulness is not controlled. It’s up to you to say no, which is hard because non-profits attract precisely the people least likely to defend their time.

It’s everybody else’s side-gig, too

As I mentioned – you can learn, and experiment with new techniques and approaches. But other people do too. If your work depends on graphic design, don’t be surprised when the designer comes up with something out-of-the-box, which naturally will be harder for you to implement, than the run-of-the-mill website.

Other people, like you, will cut corners. The designer has a family to feed, probably a day job and the thing called life. She can’t check every resolution, think about dimensions of headlines when you cram 100 characters in a title and give the proper attention to everything.

Last, but not least – without salary, recognition becomes the currency. Don’t be surprised, that “about the team” is treated as the most important page on the entire website (even if the visitors don’t care) – this is the equity paid to volunteers. Being paid with recognition also drives some folk to seek more of that compensation – they will contribute to discussions, where they have not much expertise nor understanding. These are perfect bikeshedding conditions. Beware.

Non-profits are passion-driven

Most non-profits have a mission to fix a particular problem in the world. Hunger, poor education, lack of equality, climate change – these are all areas society is failing at and non-profits are stepping in to help.

Many people are driven to work on these problems because they feel strongly about putting up with the collective screwups of society. Non-profits tend to attract people who approach most of the problems with passion and purpose, with no patience for tedious reasoning.

This leads to: 

Passion-driven-project-management

  • Urgency is the sole method of prioritization. Things are made urgent to ensure their completion, not because they actually are time-sensitive.
  • Since urgency=priority, the priorities are fluid over time.
  • Yesterday’s priority is forgotten today because somebody who feels more strongly comes in with more passion.
  • Flashy things are more important than fulfilling the initial purpose. If you are working on a website, prepare for multiple CTAs.

Non-profit survival techniques

These techniques helped me stay sane while working within a few organizations.

  1. Find a senior member of the organization to “report to”. Ideally somebody with corporate experience, and some tenure inside the Non-Profit. You don’t want to report to a committee.
  2. Never agree to do anything ASAP. Chances are, that before you get to it – the original request will change or be forgotten. Save yourself the revert.
    Bonus points for batching change requests into sprints.
  3. They will promise you texts, materials, and whatever else you’ll need. You WILL NOT get them on time. Plan accordingly.
  4. Record yourself changing stuff in the interface – this will be a good v1 for documentation so that everyone else can implement tiny changes themselves
  5. If you are creating a website – for goodness sake, use WordPress. It will save you from reinventing the wheel.
    1. With WP, you have ready tutorials to send people to, so you don’t have to fix every typo yourself. Chances are, that other folks have WP experience too.
    2. The next person dealing with the system will know what to do with it.
  6. Use a ready template, don’t work with an empty canvas.
    Yes, it will be less original than a custom-made design, but you will be able to get off the ground and focus on what’s important – content and functionality. You have no idea how many tiny details come together to make a template work.
    Implementing custom design without an hourly rate will lead to an endless back-and-forth on every detail. It costs them nothing to throw in another change.
    The constraints of an existing template work in your favor.
  7. Every statement you hear will be over-hyped – it’s a function of passion-driven project management. You have to do the mental math of halving the emotional charge of all statements.
  8. Remember to have fun. Despite unreasonable requests, the people you are working with are probably quite awesome. Don’t forget that, and schedule some time to meet them as people – not vendors of website updates.

Working in a Non-Profit is a process of realizing that the corporate environment has its advantages and lessons to teach you as well.

Coming to work on Monday to a well-oiled machine, where every cog (including you) is humming nicely, where the work flows seamlessly through the paths of well-established processes, where everything has its place is a refreshing experience. Of course, sometime around Wednesday you are sick of it all, yearning for the freedom and creativity you get to enjoy in your organization.

Automatically transcribe your Evernote voice notes

I am a big believer in taking notes and working on my personal infrastructure. I find joy in polishing the “Artur OS” and removing little pockets of friction in my setup. Have a look at my automation philosophy:

Recently, we adopted a dog and I have quite a bit of time spent walking. What if I could use it for some deep thinking?

So I wrote a bot.

How does it work?

A: I record an audio note on my phone:

B: I run my magical code

C: A transcription shows underneath

D: Profit!

There are other ways to solve this problem. Particularly, Otter.AI is a great service to transcribe your notes. However, it requires extra manual steps to open the app, export recordings, etc.

If you don’t have an elaborate setup behind your Evernote account, I recommend you check out Otter.

What do you need:

  1. You need to set up the PHP (Yes) SDK for Evernote
  2. You need an API key to Google Cloud Speech API. You don’t need a client library! Just follow these steps:
    1. Enable the API for your project here
    2. Create a new “API Interface Key” here

This code assumes you already search for a note and pass it in. I tag a note with `Tools`. A cron job periodically checks the label and does certain magical things on the notes tagged with it.

Code

It finds the audio recording in your Evernote note and transcribes it:

<?php
// https://piszek.com/2020/05/27/evernote-transcriber/
function transcribe_audio_file_in_a_note( $evernoteClient, $note ) {
// This will find the place where file is embedded, so we can display the transcription underneath.
if( preg_match( '#<en-media hash="([a-z0-9]+)"[^>]+>#is', $note->content, $res ) ) {
$id = hex2bin($res[1] );
$resources = array_filter( $note->resources, function( $resource ) use ( $id ) {
return $resource->data->bodyHash === $id;
} );
if( $resources ) {
$resource = array_shift( $resources );
}
}
if ( isset( $resource->mime ) && $resource->mime === 'audio/x-m4a' ) {
// Only audio files
if ( isset( $resource->attributes->applicationData->keysOnly['transcribed'] ) ) {
$this->log( LOG_INFO, 'This resource is already transcribed.' );
return;
}
// Set for the future
$evernoteClient->client->getNoteStore()->setResourceApplicationDataEntry( $resource->guid, 'transcribed', 'true' );
// this is your Google Speech API token
$token = "tsrtrastr8astars8tras8t";
$in = tempnam(sys_get_temp_dir(), 'evernote_transcript') . '.mp4';
$out = tempnam(sys_get_temp_dir(), 'evernote_transcript') . '.wav';
$data = $evernoteClient->client->getNoteStore()->getResourceData( $resource->guid );
file_put_contents( $in, $data );
// Because Google Speech API is crap and cannot deal with other formats, we have to recode it.
system( "ffmpeg -i $in $out" );
$data = file_get_contents( $out );
$payload = array(
"audio" => array( "content" => base64_encode( $data ) ),
"config" => array(
"languageCode" => "en-US",
"alternativeLanguageCodes" => [ "pl-PL" ], // I only use English or Polish. Your mileage may vary.
"encoding" => "LINEAR16",
"sampleRateHertz" => 44100,
"maxAlternatives" => 1,
"enableAutomaticPunctuation" => true
)
);
$payload = json_encode( $payload );
$context = stream_context_create( array(
'http' => array(
'ignore_errors' => true,
'header' => "Content-Type: application/json\r\n",
'method' => 'POST',
'content' => $payload
)
) );
// Wondering about the v1p1beta1 here? You have to use this version to have alternativeLanguageCodes. This of course is not in documentation.
$result = file_get_contents( "https://speech.googleapis.com/v1p1beta1/speech:recognize?fields=results&key=$token&quot;, false, $context );
$result = json_decode( $result, true );
if ( ! isset ( $result['results'][0]['alternatives'][0]['transcript'] ) ) {
$this->log( LOG_WARNING, 'Empty transcript. ' . print_r( $result, true ) );
return;
}
$text = $result['results'][0]['alternatives'][0]['transcript'];
$this->log( LOG_INFO, 'Transcript OK: ' . $text );
$new_body = str_replace( $res[0], $res[0] . "<div style='font-style: italic'>$text</div>",$note->content );
$note->content = $new_body;
$evernoteClient->client->getNoteStore()->updateNote( $note );
}
return $note->content;
}

More of my adventures in automation:

React Native Isomorphic app in a weekend

TeamParrot is an app that reads your Slack scrollback out loud so you can listen to your coworkers while doing awesome stuff.

Because I work in a distributed company and have coworkers all around the globe, every day I wake up to a full wall of scrollback to go through. Some of it is actionable, some of it is just chatter, but its good to at least have a vague notion of what is going on.

I also value efficiency and not wasting time, so I came up with TeamParrot.

Having an app in the app store was on my Bucketlist for some time, so I jumped on this simple idea like an angry Twitter user on a chance to humiliate someone.

These days, I usually work with React and React Native seems like an ingenious way to get my feet wet in the pool of app development

Before we even start, I assume you read the official docs – they are pretty decent these days.

Starting a React Native project

Starting an RN project was pretty easy and as many projects these days, starts with a generator.

You have to install RN as a global npm module and then you generete a project, as noted here:

npm install -g react-native-cli
react-native init AwesomeProject
cd AwesomeProject
react-native run-ios

You just provide a name and then the tool creates a project for you.

The project builds in XCode and Android SDK.

Few notes about Android sdk:

  • You DONT need Android studio and it is a terrible piece of software
  • Android SDK is a set of command-line tools
  • These tools install their own libraries, device images, etc. There are multiple versions and each of the files is surprisingly huge. That is one of the reasons that Android development is such a hassle. I would really love some cloud build system
  • Emulating is also a hassle. Genymotion was good solution for me, but you need to point it at the same image files you use to build your software

Renaming a React Native project

Of course I provided a bad name and then had to rename my project. Read about it here:

https://piszek.com/2017/02/07/react-native-rename-my-app/

Using external APIs

Your app needs to connect to an external Oauth? We got you covered!

https://piszek.com/2017/01/29/react-native-oauth/

Using libraries / internal APIs

As you may have heard, React Native does not use WebView like many other JavaScript mobile app technologies ( Cordova for example ).

In RN, higher-order native components ( sometimes big pieces of an app ) are used to piece together you interface. These components have JavaScript wrappers and you can use them as you would any React component. Because these components are pure native, the app behaves just as fast as native. Many components are already wrapped by Facebook in the official repo, even more have sprouted as npm modules. I needed Text-to-speech library for TeamParrot and I found a few.

If you are using a component/library that adds some native code, you need to link it.That means adding the native code parts to the build process of your app. Usually, the automatic tool `rnpm` will do that for you, so when you type

rnpm link

or

rnpm link library-name

You should be done.

Sometimes it involves few manual steps – putting imports here and there in the native code.

Adding flair

Few pieces like that require fiddling with the native code are Icons and Fonts:

https://piszek.com/2017/02/01/react-native-vector-icons-fontawesome-and-others/

Files structure and isomorphic code 

zrzut-ekranu-2016-11-12-o-19-37-20

By default, you will have `index.ios.js` and `index.android.js` and as you can imagine – one is an entry point for your app in iOS, the other is the entry point for you Android code.

By default, your codebases are separate, but don’t be discouraged! There is one weird trick that programmers will hate you for!

Just put this both in `index.ios.js` and `index.android.js` :

import { AppRegistry } from ‘react-native’;
import Main from ‘./main’;
AppRegistry.registerComponent( ‘YourApp’, () => Main );

That way, both of your entry points use the same main component.

My folder structure of choice is

  • android
  • app.js – main logic
  • assets
  • components – these are dumb components
  • config
  • index.android.js
  • index.ios.js
  • index.web.js
  • ios
  • lib
  • login.js
  • node_modules
  • package.json

What is “index.web.js” you ask? Well, this app builds in web too! That means that I can develop my UI in chrome devtools !

Read more about isomorphic prototyping here

Release

Is your App ready for the big day? Not so fast! You have to submit it to the review.

Releasing in App Store

  1. Get Apple developer account
  2. Register yourself in itunesconnect
  3. Create your provisioning keys in XCode
  4. Create a bundle
  5. Sign it
  6. Upload to App store
  7. If you want to invite beta testers, you still need to submit it for a review

You want to update your app post release? Dont forget to configure CodePush! 

Maketing

 That is an entry even in itself and maybe a post for later!

But with these steps you should be able to make most of the simple apps out there.

Some other valuable links

React Native Isomorphic app over the weekend

This article is part of my “React Native Isomorphic app over the weekend” series. It shares the problems I encountered during development of TeamParrot and Headstart Journal.

[display-posts tag=”React-Native-Weekend” wrapper=”ul”]

React Native CodePush

CodePush is a magical service that lets you update your app on the fly! It means that when you find a bug in your app you can push the code instantly to your users and update their apps / release new features.

Why should I care?

With Native apps you have to go through app review process every time you release a new version. Sometimes its fast, sometimes its not. But with CodePush you can update JS part of the app bypassing the review!

Me wants!

Setup is actually quite easy and documentation pretty good. You  need to:

  1. Install CLI tools
  2. Register your app
  3. Install CodePush in your app
    npm install --save react-native-code-push
    react-native link react-native-code-push
    
  4. Wrap your top-level component in a codepush wrapper
    import codePush from "react-native-code-push";
    class TeamParrot extends Component {
    ...
    }
    export default codePush( TeamParrot );
    
  5. Add deployment keys to your project
    1. iOS: add to info.plist:
      
      CodePushDeploymentKey
      your key
  6. To update and rollback your app:
    code-push release-react TeamParrot-ios ios
    code-push promote TeamParrot-ios Staging Production
    code-push rollback TeamParrot-ios Production
    
  7. Profit

React Native Isomorphic app over the weekend

This article is part of my “React Native Isomorphic app over the weekend” series. It shares the problems I encountered during development of TeamParrot and Headstart Journal.

[display-posts tag=”React-Native-Weekend” wrapper=”ul”]

React Native: Rename my app

You started building your app before you knew what it was, didn’t you? Well, that is certainly what I did.

My app started as “SlackBird”, then I realized that i may be violating some trademark there ( hint: probably not “bird” ), so I went and changed the name to “TLDR“. But after that I realized my addiction to Party Parrot so “TeamParrot” it is!

So what files should I actually change?

IOS

  • When you go to project details in Xcode, you can edit name. When you edit it, Xcode “Rename files” tool opens.Screen Shot 2016-10-19 at 22.37.32 PM.png
  • In ios/PROJECT/info.plist change CFBundleURLName
  • In ios/PROJECT.xcodeproj/xcshareddata/xcschemes/PROJECT.xcschemechangeBuildableName`
  • Rename file ios/PROJECT.xcodeproj/xcshareddata/xcschemes/PROJECT.xcscheme itself to NEWPROJECT.xcsccheme

Android

I just grepped for files containing my old name “TLDR” in this instance. These variables needed to be changed:

  • package in android/app/BUCK
  • applicationId in android/app/build.gradle
  • package in android/app/src/main/AndroidManifest.xml
  • return value of getMainComponentName in android/app/src/main/java/com/slackbird/MainActivity.java . That is the name of your main component in JavaScript portion.
  • package in android/app/src/main/java/com/PROJECT/MainApplication.java
  • Application name in android/app/src/main/res/values/strings.xml

React part

Now you renamed your min entry point to your application. So don’t forget to rename your main component name:

AppRegistry.registerComponent( 'TeamParrot', () => Login );

If you renamed everything, some directories will still have old name of your app. I decided I’m fine with that.

React Native Isomorphic app over the weekend

This article is part of my “React Native Isomorphic app over the weekend” series. It shares the problems I encountered during development of TeamParrot and Headstart Journal.

[display-posts tag=”React-Native-Weekend” wrapper=”ul”]

React Native: Vector Icons – FontAwesome and others

You want some nice icons in your app, don’t you? In my laziness I tried using emojis instead, but it turned out to be sub-par.

So I conceded and installed an icon package called

React Native Vector Icons

npm install react-native-vector-icons --save to install

How this works

This package provides fonts and some wrappers. Since SVG is still not working 100% on RN, introducing vector icons via font seems like a reasonable approach. In mobile apps you want to bundle the font with the app itself.

IOS

Theoretically, you should be able to rnpm link. Unfortunately, that didn’t work for me, so I had to install font manually:

  • Drag “Fonts” folder from node_modules/react-native-vector-icons to your project
  • You have to add fonts in info.plist This is how I added FontAwesome only:

UIAppFonts : Fonts/FontAwesome.ttf

ANDROID

In android/app/build.gradle

project.ext.vectoricons = [
    iconFontNames: [ 'FontAwesome.ttf' ] // Name of the font files you want to copy
]

apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"

In android/settings.gradle :

include ':react-native-vector-icons'

project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android')

Using

Now you want to plaster icons all over your application, don’t you? I do too!

If you are using Font Awesome like me, you would go to http://fontawesome.io/icons/ and pick your icon. You need the name without “fa-” at the beginning, and then you drop icon in your project like so:

import Icon from 'react-native-vector-icons/FontAwesome';

WEB

Because my project is isomorphic, this caused some problems in the web version. react-native-web is not yet compatible with react-native-vector-icons. To make the project even compile on the web, I made 3 files that abstracted the icon enough:

icon.web.js

import React from 'react';
import { Text } from 'react-native';
export default Text;

index.android.js and index.ios.js

import Icon from 'react-native-vector-icons/FontAwesome';
export default Icon;

Because isomorphism works in react native by picking specific files, my project now builds under all 3 environments. Granted, I would prefer it to build for web with working icons, which it does not do currently, but thats a battle for another day.

React Native Isomorphic app over the weekend

This article is part of my “React Native Isomorphic app over the weekend” series. It shares the problems I encountered during development of TeamParrot and Headstart Journal.

[display-posts tag=”React-Native-Weekend” wrapper=”ul”]

React Native Web & Isomorphic magic

One of the most appealing qualities of React Native is the idea of isomorphic code. Code, that can run on both iOS and Android, enabling you to write 2 apps at the same time.

But, there is another benefit to isomorphic code. You can also speed up writing your code just for one app.

Since react Native is using React code, I initially wanted to develop parts of the application “the React way”, using hot reloading, React Devtools and the fast feedback cycle that web development permits. That would let me work on the app without emulators and building the code.

It’s possible and much more.

React-Native-Web

‘react-native-web’ builts your react native app as a web app. Not pieces and snippets, but the whole app. Granted, there is a lot of functionality missing, so it’s almost certain that you will have to modify your source a bit to even make the build work, but there is one use-case that it’s perfect for:

UI components.

In TeamParrot I have separated all UI components as “dumb components” without much logic nor dependencies. That way, I can develop UI separately from the whole app. I have made specific container-component for web that holds all of these dumb components and allows me to see all of them in one place, iterate and work on in my web browser.

Let’s do this!

If you want this also for your app, here is how I’ve done it for TeamParrot:

React-Native-Web-Starter

I used react native web boilerplate called react-native-web-starter to get started. I downloaded the latest master, dumped the files into root of TeamParrot project and… Build failed. Now web, ios, and android build stopped working.

Now, let’s fix it!

First need proper libraries in your package.json devDependencies:

"react-native-web": "^0.0.39",
"babel-core": "6.9.1",
"babel-loader": "6.2.4",
"babel-plugin-transform-decorators-legacy": "1.3.4",
"babel-preset-es2015": "6.9.0",
"babel-preset-react": "6.5.0",
"babel-preset-stage-1": "6.5.0",
"babel-runtime": "6.9.2",
"webpack": "1.13.1",
"webpack-dev-server": "1.14.1"

You need to remove .babelrc provided by react-native-web-starter, since that will interfere with RN babel build process. But the configuration from .babelrc needs to end up somewhere, so you need to modify your package.json loader to include:

{
    test: /\.js$/,
    exclude: /node_modules/,
    loader: 'babel-loader',
    query: {
        cacheDirectory: true,
        "presets": [
            "es2015",
            "stage-1",
            "react"
        ],
        "plugins": [
            "transform-decorators-legacy"
        ]
    },
}

Everything seems ok at this moment, but the app still does not want to load. After debugging for a while it turned out that these components didnt want to play nice with React Native Web:

  • Switch used for toggles
  • Icon from `react-native-vector-icons`
  • RefreshControl used for “Pull to refresh” on iOS.

I decided on a n ugly solution that I would just render “Text” instead of Icon and not render Switch or RefreshControl at all by passing “webDevelopment” prop:


export default function MainView( { queue, playing, channels, stop, pause, play, refresh, loading, header, openDrawer, webDevelopment = false } ) {
	const msg = get( queue, [ 0, 'items', 0 ] );
	const scrollProps = { style: { flex: 4 } };
	if ( ! webDevelopment ) {
		//When building this component inside react-native-web, RefreshControl does not work correctly
		scrollProps[ 'refreshControl' ] = ;
	}

The last problem I needed to solve was loading images. React Native has a an Image component, to which you pass local images by require prop:

To make this work on web, with webpack, you need to install file-loader:

npm install –save-dev file-loader

Webpackconfig

it’s located under /web/webpack.config.dev.js :


const path = require('path')
const webpack = require('webpack')

const DIRECTORY = path.join(__dirname)

module.exports = {
    devServer: {
        contentBase: path.join(__dirname, 'src')
    },
    entry: [
        path.join(__dirname, '../index.web.js')
    ],
    module: {
        loaders: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                loader: 'babel-loader',
                query: {
                    cacheDirectory: true,
                    "presets": [
                        "es2015",
                        "stage-1",
                        "react"
                    ],
                    "plugins": [
                        "transform-decorators-legacy"
                    ]
                }
            },
            {
                test: /\.(png|jpg|gif)$/,
                loader: "file-loader?name=img/img-[hash:6].[ext]"
            }
        ]
    },
    output: {
        filename: 'bundle.js'
    },
    plugins: [
        new webpack.DefinePlugin({
            'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
        }),
        new webpack.optimize.DedupePlugin(),
        new webpack.optimize.OccurenceOrderPlugin()
    ],
    resolve: {
        alias: {
            'react-native': 'react-native-web'
        }
    }
}

Actual web code

This is my index.web.js:


import { AppRegistry } from 'react-native'; import Screens from './web/screens';

AppRegistry.registerComponent('App', () => Screens); AppRegistry.runApplication('App', { rootTag: document.getElementById('react-root') } );

Let’s roll!

And this is how I run my webpack dev server:

webpack-dev-server --port 3000 --config web/webpack.config.dev.js --inline --hot --colors --quiet

Zrzut ekranu 2016-11-12 o 19.37.20.png
Beauty of developing React Native app in devtools

Try it! It really speeds up the whole process!

React Native Isomorphic app over the weekend

This article is part of my “React Native Isomorphic app over the weekend” series. It shares the problems I encountered during development of TeamParrot and Headstart Journal.

[display-posts tag=”React-Native-Weekend” wrapper=”ul”]

React Native: Oauth

If you want to use any self-respecting API on the web, you are going to need Oauth authentication. If you need an explanation what oauth is, there are plenty better ones. These are the steps your app needs to go through:

  • Send user to special URL in the browser that lets them log in to the service
  • Handle callback URL from this service
  • Exchange keys with the service to make sure callback was legit
  • Store the token.

Since I used Slack API from the slack npm package, I had the “Exchanging the keys” parts ready.

0. Preparing the app

You thought we were going to start from 1, didn’t you? Well, you you must be new to this “programming” stuff. 😃  On the more serious note, you need to register your app in the API provider to get special keys for the step 1 and fill in URL for the step 2.

For TeamParrot, I set up following OAuth redirect URL:

Zrzut ekranu 2016-10-30 o 16.29.31.png

1.Send a user to the special URL

You will need to use “Linking” library. DO NOT confuse Library called “Linking” with the process of “Linking libraries”, which is tying native libraries to JS code. I just send my users to 'https://slack.com/oauth/authorize?client_id=' + client_id + '&scope=channels:read%20channels:history%20users:read%20channels:write' and that opens web browser with appropriate “back” button.

2. Handling callback URL

If all goes good and your users give you appropriate permissions, they will be sent to the URL you specified in step 0. You may notice that this step has a weird protocol (team-parrot://). It actually can have any protocol you want that’s not used by an other app. This is enabled by “Deep linking” and “Intents” On android.

iOS

First, you need to configure your app to handle this specific link you want to capture. That tells the operating system to route those links to your beautiful and shiny app. As per usual, you have to do that in info.plist :

<string>com.piszek.teamparrot</string>
<key>CFBundleURLSchemes</key>
<array>
<string>team-parrot</string>
</array>

For a reason I completely do not understand, you also have to mess with a bit of Native code. More info in the docs

So, in file ios/SlackBird/AppDelegate.m :

@implementation AppDelegate
+- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
+  return [RCTLinkingManager application:application openURL:url sourceApplication:sourceApplication annotation:annotation];
+}

Android

Deep linking is called “intents” in Android and much of the same concept applies. You have to tell the OS that you want to open certain protocol inside your app. So:

In android/app/src/main/AndroidManifest.xml

<activity android:name=".MainActivity"
+        android:launchMode="singleTask"
...
>
+        <intent-filter>
+          <action android:name="android.intent.action.VIEW" />
+          <category android:name="android.intent.category.DEFAULT" />
+          <category android:name="android.intent.category.BROWSABLE" />
+          <data android:scheme="team-parrot"/>
+      </intent-filter>

OAuth walkthrough

Now you are ready to become a Oauth Sith and step to the dark side. This is how you oauth:

Linking.openURL( 'https://slack.com/oauth/authorize?client_id=' + client_id + '&scope=channels:read%20channels:history%20users:read%20channels:write' );
Linking.addEventListener( 'url', handleUrl );

And now your function “handleUrl” will be responsible for confirming “CODE” and exchanging it for a token. Usually, that will be handled by your API library of choice. Here is how I did it for TeamParrot:

import { client_id, client_secret } from '../config/slack';
import exchangeCode from 'slack/methods/oauth.access';
import testAuth from 'slack/methods/auth.test';
import { Linking } from 'react-native';

export function login() {
    return new Promise( ( resolve, reject ) => {
        Linking.openURL( 'https://slack.com/oauth/authorize?client_id=' + client_id + '&scope=channels:read%20channels:history%20users:read%20channels:write' );
        Linking.addEventListener( 'url', handleUrl );
        function handleUrl( event ) {
            const error = event.url.toString().match( /error=([^&]+)/ );
            const code = event.url.toString().match( /code=([^&]+)/ );
            if ( error ) {
                reject( error[ 1 ] );
            } else if ( code ) {
                exchangeCode( { client_id, client_secret, code: code[ 1 ] }, ( err, data ) => err ? reject( err ) : resolve( data ) );
                Linking.removeEventListener( 'url', handleUrl );
            } else {
                reject( 'params' );
            }
        }
    } );
}

export function testLogin( account ) {
    return new Promise( ( resolve, reject ) => testAuth( { token: account.access_token }, ( err, data ) => {
        if ( err || data.user_id !== account.user_id ) {
            reject( err, data );
        } else {
            resolve( Object.assign( {}, account, data ) );
        }
    } ) );
}

So there you have it. Now, you should be authenticated over Oauth2 with the slack API and able to make calls.

React Native Isomorphic app over the weekend

This article is part of my “React Native Isomorphic app over the weekend” series. It shares the problems I encountered during development of TeamParrot and Headstart Journal.

  • Oauth
  • Vector Icons – FontAwesome
  • CodePush
  • Renaming an App
  • Web & Isomorphic code development in Chrome devTools
  • Whole story

[display-posts tag=”React-Native-Weekend” wrapper=”ul”]

I wanna be a programmer! A journey.

Ordinary World

Chuck was few years into his career. He was sitting at a desk for most of the day, doing menial and repeatable tasks, filling out Excel spreadsheets and agonizing over “ASAP” PowerPoint presentations that nobody really paid attention to during meetings that were absolutely unnecessary.

But the absolute majority of his day was consumed by Facebook. Be it boredom or burnout, he compulsively checked his stream. And to add salt to the injury, pretty often he would stumble into a story how those fresh-out-of-college programmer-people got an obscene salary, office restaurant, laundry, assistant or something as ridiculous as an office with michelin star-train chefs for YOUR DOG. No, seriously.

Call to adventure

Chuck said to himself: I wanna be a programmer! I have plenty of friends in the industry and I will ask them what to do.

Refusal of the Call

Lets start with education. I don’t have any formal engineering education! These people had to learn this in school, didn’t they? Maybe it’s not such a great plan, I don’t want to spend another 3 years studying something, do I?

Supernatural Aid

After a chat with one of his friends, he learned that IT is one of those weird professional industries, where formal education is not that important. In many other industries, you show your diploma to convince prospective employer that indeed, you know what you are doing. But in IT, diploma is close to obsolete because the education has trouble keeping with technological progress.

You don’t need formal engineering education

Furthermore, programmers are in high demand. In Silicon Valley, companies are poaching employees from each other because the demand highly outgrew “tech talent” there.

Should I go for code bootcamp?

Bootcamp is an intensive few-weeks coding course. It worked for some of Chuck’s friends, but he knew that it would be a bad choice for him. He was always a self-learner and he despised the fact that in a group setting you need to go as slow as a dumbest person in the class or sometimes he needed more time but the group needed to push forward.

One advantage of coding bootcamp is discipline and accountability. The are in charge and they motivate and keep the score. In Poland, Coderslab appealed to him and he wasn’t girly enough for girlsjs, but he wanted to learn on his own terms.

Crossing the Treshold

SONY DSC

A friend recommended Code.org to Chuck. It was created by Facebook and few other companies as an effort to teach kids how to code. Chuck played with few lessons and decided he felt confident enough to try something more serious.

The road of trials

What programming language should I learn?

When he started asking this seemingly innocent question, clearly he had no idea what he was getting into. He didn’t mean to question anybody’s religious beliefs, but every time he brought the subject up, he got a different, strong opinion.

Chuck decided to listen to Artur’s advice and learn JavaScript. Following arguments convinced him:

  • JavaScript is one of the few languages that can be used in many layers of application. That meant that he would be able to switch positions without acquiring new language,
  • With React Native and other approaches it is now possible to also write mobile apps in JavaScript. If he decided to, he could write his own apps!,
  • JavaScript ecosystem is still growing rapidly. The demand will only grow.

So he started taking advantage of the amazing free material available on the web:

He also heard good things about a comprehensive free “How to be a programmer” guide.

The inmost cave

Contribute! Show off!

Chuck decided to call one of his friends who was responsible for hiring in a huge company.

  • “Listen”, asked Chuck, “If you are not looking at diplomas, how DO you know who to hire?”
  • In many companies it boils down to something called “technical interview”. Honestly, it’s exam-like situation, where we ask technical questions, ask you to solve some problems and generally grade you
  • Is this a reliable process?
  • No, it’s very sloppy and a bit random.
  • Ok, but how can I prepare?
  • I recommend Cracking Code Interview. These are hard and this books is really all you need to get into Google or Microsoft. But in many companies it’s MUCH easier. Usually it’s a few random questions related to specific programming language.
  • Is there something else you would recommend?
  • Open Source projects! It’s an easy way to get experience and make your CV stand out.
  • How do i start with that?
  • Start with Contributing to GitHub. There are plenty of projects that would appreciate help. You will learn A LOT! Pro tip: Best way is to try to set up the project and start by fixing the “README” files. If you had to overcome some obstacle – fix the readme’s before the code. The maintainers of the project will appreciate your help and it will count as contribution. Also check out this guide on starting your Open Source contributions
  • Thanks for the chat!

The supreme ordeal

How do I get motivation?

At this point Chuck felt a bit overwhelmed by possibilities and work to be done. Fortunately, one of his friends had a masters degree in psychology, so he asked him how to find a drive and strength to push forward.

His friend responded:

I have learned more about self-motivation from “Awaken the giant within” by Tony Robbins than during 5 years of psychology.

The book was a splendid recommendation. Chuck never felt so driven to get this done!

Reward

How much will I earn? How to find a job?

Chuck started asking himself what he should learn in order to get a job. What are the requirements? He heard it’s much better to just look for the offer in specific programming language he knew, so he can focus on improving his skills before he starts learning more.

The Road Back

I want to work remotely, like this Artur person!

What is this remote work? How come Artur is writing posts from all over the globe? Chuck managed to call Artur and ask how to get remote work

“Chuck, listen: there are some fully-distributed companies, but they are only functioning because people there are self-driven. It’s hard to control people when they are not in the office, so we need to be very careful in hiring. Almost always they require prior experience and I highly recommend first starting in some other company”

Resurrection

What’s next?

At the beginning of his programming career, Chuck decided to go for big / medium company. He heard, that he definitely should not join “a cool startup of his friend”. It could be bad for him and the startup.

  • Big company has processes and resources to teach more basics
  • His shortcomings will have little impact on the final result
  • There will be more “newbies”, so he wont feel like the only one without 10+ years of experience
  • There will be plenty patterns / good practices to absorb
  • In a big company it’s much easier to know what he doesn’t know

Chuck got a cool job at Samsung. He decided that he will learn constantly in his new job and after 2 years of corporate experience, he will try to step up the corporate ladder or get a better position somewhere else. Changing job in tech every ~3 years is considered normal.

Be smart, be like Chuck. Be a programmer. It’s awesome.

Return

Why are these header titles so weird?