Brian Pfeil

Minotes

There are many choices for notes apps out in the App Store. So many that it’d be a couple days effort just to look into and evaluate them all. Everything from the built-in simple Notes app to the feature packed Evernote. A notes app is one of those utility apps that gets a lot of mileage like mail and weather. Something with high usage you want the most efficient and streamlined app. It’s also something that becomes personal and people get attached to.

I wanted something extremely simple, clean up, and fast. I started with the simplest possible solution of a single text view you could type in. From that, the ability to create multiple notes was added, but I didn’t want the freedom to create as many notes as you want. Having constraints on the number of notes forces the user to create more meaningful notes and manage / clean up notes. The goal with minotes is not to have an archive of all historical notes with search, etc. The type of notes appropriate for this app are short-lived ones and in general have a lifespan of around a week. I landed on a UI metaphore similar to mobile safari with a max of 9 notes.

Preferences around typography and text size is something that is really needed in order to be useful for more than a specific set of users. For example, older people may need a little bit larger font size, whearas younger users may want to cram more text on the screen and are fine with a smaller font size. In order to keep it simple, there are three typefaces to choose from and in sizes, small, medium, large.

It’s an opinionated app built with my specific needs in mind. It’s doesn’t try to appeal to all users univerally, but if you like simple purpose built apps, check it out.

Minotes Product Page

Hosting Static Sites on Heroku

I was recently creating a web site for a family member, and was looking around for the best place to host it. It’s a simple personal site that only contains static content. There are many options out there from the freebie wordpress options to rackspace and the like. None of the “web publishing platform” type sites were a fit because I wanted full control over the layout, and look and feel of the site.

I’ve been working with Heroku for my day job for web applications, and it’s been simple to get things up and running at no cost. Heroku allows you to create a web application for free, and only if you need to scale to support the traffic do you have to pay.

One of the limitations of using the free plan with heroku is that if your app hasn’t recieved any traffic within an hour, it puts it into an idle state. They call this dyno idling and when a request comes in and your dyno is in an idle state, it has to spin it back up, and that takes time. In my experience, I’ll go to hit the site and it takes approx. 5 seconds to respond. It’s free, so I can understand when they do this to save on compute resources, and if you have pay / have multiple dynos, they never with idle your app.

To work around this you just need to have at least 1 request come in an hour. There are many ways to do this, and I took the simple approach of using a monitoring service (pingdom) to check/ping the site for availability every 5 minutes. You could also implement by using a background worker process.

There’s a great Creating Static Sites in Ruby with Rack walkthrough on the heroku dev center that will have you up and running in few minutes. They provide a fully functional sample application that you can modify to make you own.

RubyMotion

RubyMotion

RubyMotion is a toolchain that lets you develop iOS using Ruby. I’m a big fan of Ruby and have been using it on and off since 2001. It’s been a huge timesaver in many cases allowing me to quickly script solutions. When I heard it was coming to iOS I had to check it out.

The toolchain and the way you use the various components matches the rails development process. Open your favorite text editor and a terminal, and you’re ready to go. For example to create a new project.

1
motion create project

Interfacing with the toolchain is all rake driven. Edit your files, type rake device, and your app is compiled and launches in the iOS Simulator. It’s a very nice and familiar development process.

One of the big benefits with using Ruby is concise code. Compared to Objective-C, you’ll end up with a lot less code for an app. For example with Ruby, you could put your entire app in a single .rb file. With Objective-C you have the .h and .m files for every class, and you spend quite a bit of time switching between them all.

Ruby helps ease the app development process, but most of the learning and skill with iOS development is understanding the various iOS frameworks. This doesn’t go away with RubyMotion. You still have to take the time to learn these. Part of learning is reviewing the code samples that Apple provides, and they’re all in Objective-C. Knowing the native language of a platform is always the best thing, and if someone wanted to get started with iOS development, I’d recommend learning Objective-C.

RubyMotion costs $200, and this might be a barrier for it taking off. The Ruby community is used to things being open source and free. It’d be nice if they took the approach Apple does with Xcode. With a free Apple Developer account, you can create apps, but your limited to running them in the simulator. Once you pay the $99 for to be a part of the developer program, you can put apps on devices and the App Store. RubyMotion could do the same, free for apps running on the simulator, and purchase to put apps in the App Store.

I’m skeptical that it’ll take off, but am definitely rooting for it.

Emailing Todos to Dropbox

Between work and home,I’ve always got more things to do than I can keep straight my head. Like most people, I keep a to-do list so I don’t have to worry about forgetting it. My to-do list is a simple bulleted text (Markdown) file that I keep in Dropbox so I can access it from anywhere.

example TODO.txt file
1
2
3
4
5
6
7
8
9
10
# TODOS

* get gas
* get leaf bags
* send thank you cards

# Completed

* get propane
* get burgers and hot dogs

This setup works fairly well, but they’re times when I think of something I need to do, but I don’t get it into this list because of the time it takes to add it. The usual scenario is that I’m not sitting in front of a computer, and I need to add it using my iPhone. There are plenty of to-do and dropbox text file editor apps our there to choose from (way too many), but none of them make it fast enough to enter, and fit my to-do-list-text-file-in-dropbox setup.

The best case scenario would be an app, that opens awaiting my next to-do, and I’d just type it in, and it’d add it to my to-do list text file in dropbox in the right format. I thought about making an app that did just that, but I knew there had to be an easier way. That’s when email popped into my head. It’s dead simple, and available everywhere. I’d never have an excuse not to get something on the list. It’s also fast and easy to send email.

Solution

My solution is to send an email to a special “todo” email address where the subject would be the todo item, the email would be processed, and the item added to my to-do list text file in dropbox.

Google App Engine lets you run web apps on Google infrastructure for free, and they offer a way to receive and process email. Dropbox provides a Dropbox Python SDK to get at your files, which is works out nicely since Python is the primary language used for App Engine development.

You can take a look at the Google App Engine Receiving Email Documentation, but the gist of it is that an email sent to NAME@APP.appspotmail.com will result in a HTTP POST request sent to /_ah/mail/NAME@APP.appspotmail.com with the POST body containing the contents of the email. Google provides a nice InboundMailHandler class to make handling inbound email a breeze.

The first thing we need to do is to map a handler for inbound emails. I’m using the Django Python web framework in my app engine app, which provides some connivence mechanisms. To map a URL to a handler we add the following to the urls.py file.

urls.py
1
2
urlpatterns = patterns('',
    (r'^_ah/mail/todo@myapp.appspotmail.com$', 'emailengine.views.todo_email_handler'),

We mapped the url to todo_email_handler method

emailengine/views.py
1
2
3
4
5
6
7
8
9
def todo_email_handler(request):
    if request.POST:
        message = mail.InboundEmailMessage(request.raw_post_data)
        logging.info("Received a message from: " + message.sender)
        if is_whitelisted_email_address(message.sender):
            mgr = DropboxManager()
            mgr.add_todo(message.subject)
            logging.info("Received a message from: " + message.sender + ", Todo:" + message.subject)
    return HttpResponse('ok')

In order to prevent anyone from adding to-do items to my list, I added the is_whitelisted_email_address method to restrict processing of emails to only those that come from me.

emailengine/views.py
1
2
3
4
5
6
7
def is_whitelisted_email_address(email):
    result = False
    for whitelist_email in EMAIL_ADDRESS_WHITELIST:
        if email.lower().find(whitelist_email) != -1:
            result = True

    return result

The work to add the to-do item to the TODO.txt file in dropbox is

1
2
mgr = DropboxManager()
mgr.add_todo(message.subject)

I created the DropboxManager class as a simple wrapper around the Dropbox API. This keeps the code tidy, and all the dropbox specific code like the app key, secret, and token in one place.

Conclusion

I’m sure one of the many existing to-do list apps fits the needs of most people. This solution required a little work upfront, but has already proven to be a timesaver.

Best Fit Web Font Sizing

I’ve been working on a web app that targets both smartphones and tablets. The large variation in screen sizes has sent me down the path of using a dynamic proportional layout that adapts to fit the available space. For example, I’ve allocated 20% of the available vertical space to the header section that displays a title. The jQuery UI.Layout Plug-in has worked great for laying out the content areas, but I ran into a wall when it came to sizing my text proportionately.

The basic problem is that I have a box, and I want to display some text in it at the largest font size without it being wrapped or clipped. The only way to determine the bounding rectangle a string of text with certain font characteristics, is to create it, add it to the DOM, and then measure it. The following function does just that.

function sizeWithText(text, cssStyles) {
    // create temp element to hold our text
    var e = document.createElement('span');
    e.appendChild(document.createTextNode(text));
    
    // apply any styles that have been passed in
    // to our element - these can affect the text size
    for (var prop in cssStyles) {
        e.style[prop] = cssStyles[prop];
    }
    
    // hide our temp element
    e.style['visibility'] = 'hidden';
    
    // add to DOM in order to have it render
    document.body.appendChild(e);
    
    // get the bounding rectangle dimensions
    var s = {w: e.offsetWidth, h: e.offsetHeight};
    
    // remove from DOM
    document.body.removeChild(e);
    
    return s;
}

The cssStyles parameter holds the other css style attributes that you’d like to apply to the text. For example, you might have a font-weight: bold attribute that increases the size of the text, and we want to make sure we account for it.

Now we can use this function to check whether text with a font size and a set of styles will fit in our box. We set the font size to 1 and continuously increase it by 1 check whether it’ll fit at every iteration. As soon as it doesn’t, we stop.

function bestFitTextSize(text, css, width, height) {
    var pixel = 1;
    
    do {
        css['font-size'] = (pixel++) + 'px';
        s = sizeWithText(text, css);
    } while ( (s.w < width) && (s.h < height) )
    
    return pixel - 2;
}

This is a brute force and inefficient way to do the calculation, and there are improvements that could be made. We could start at a reasonable font size like 6px, increment by standard font sizes, etc., but this is fine for my usage where I only do it once on app load.

Here’s a code sample that shows how the previous functions are used.

// box we want to fill with text
var c = document.getElementById('content');

// out text
var text = 'Lorem ipsum dolor sit amet';

// styles
var cssStyles = {
    'font-family': 'Impact',
    'font-style': 'normal',
    'font-weight': 'bolder',
    'letter-spacing': '1px',
    'text-shadow': '3px 3px 3px white'
};

// size the text to fit
function applyBestFitText() {
    // get the pixel size for the font
    var px = bestFitTextSize(text, cssStyles, c.offsetWidth, c.offsetHeight);
    cssStyles['font-size'] = px + 'px';
    
    // set the text
    c.innerHTML = text;
    
    // apply our styles
    for (var prop in cssStyles) {
        c.style[prop] = cssStyles[prop];
    }
}

// adjust if the size changes
window.addEventListener('resize', applyBestFitText, false);

// call for first time adjustment
applyBestFitText();

The complete example is available as a gist

Metro UI: Initial Thoughts

I’ve been digesting all the new information around Windows 8 and Metro over the past week. I’ve watched the BUILD Conference Channel 9 Videos, read the articles and docs on the Windows Dev Center and the Building Windows 8 blog. The best resource for your time on learning what Metro is all about from a design perspective is 8 traits of great Metro style apps.

The Metro Style interface is a totally new and original approach to UI. Microsoft put a lot of thought into the design of it, and they demonstrated this by providing background during the BUILD sessions on how they studied how users held and used slate devices, what areas of the screen where reachable by their thumbs, etc.

The concept of dedicating all the available screen space to content with no chrome makes perfect sense. It doesn’t makes sense for all applications, especially those rich in functionality. For example, Microsoft showed Photoshop and it’s many tool palettes and menus, and it was clear that you wouldn’t make a Metro Style Photoshop app. Metro makes sense for “consumery” type apps like casual games, productivity apps, and rich media apps; the same things you see on an iPad or Android tablet. This is one of the reasons that they need to support “classic” windows app, and they can’t make a clean break to the Metro Style UI.

One potential problem with the immersive content, and no chrome approach is the lack of discoverability to take actions on the content. Metro relies heavily on gestures that take place at the edges of the screen. For example to display the charm bar, you place your finger off to the right of the screen where there isn’t any content and touch isn’t recognized then swipe in towards the center of the screen. Another example is the application bar at the bottom where you have to swipe up to summon it. Is a user gonna know to do this? Will devices come with an in-your-face tutorial on these things when you first boot it up? There have been many studies that have proven if it’s out of site then users won’t discover it. For touch, there are only two gestures you should assume your users know, and that’s tap and swipe to scroll; everything else is power user territory.

There’s another issue around using a mouse in Metro. Microsoft made the statement that Metro is a natural fit for a mouse in addition to touch. I’ve been using the Developer Preview running in VMware, and using a mouse with Metro is very tedious. The level of indirection you have between the mouse and what happens on the screen makes the things that work well with touch feel like a large amount of effort. I actually resorted to using the windows 8 keyboard shortcuts. to activate the standard toolbars and menus because it was so painful. If the apps interaction is limited to clicks and/or keyboard input with no application bar, then the mouse could work, but that’s only gonna be a handful of apps.

The tiles interface for the home screen was very visually appealing in all the BUILD demos with nice typography, rich pictures, and pastel colors. This is great and demos well when Microsoft controls all the apps, but what happens when you have a whole community of app developers who have their own opinions on design and style building Metro apps. The app that doesn’t use a pastel color for their tile background, shows a poorly shot overexposed photo that the user took on their phone, uses an ugly icon, etc. There’s nothing from keeping people from doing this. Microsoft is aware of this and they emphasized many times in the BUILD sessions to use the templates they provide in Visual Studio 11. This is a problem on any platform, and it happens on iOS and Android, but the reason it’s a bigger issue for Metro is that it’s critical to have in place for the immersive experience. All you have is content. You don’t have standard chrome title bars and toolbars with a standard look and feel to make your app fit in. Content is everything, and if it’s poor, then it’ll stick out like a sore thumb.

It’s still early. Microsoft always previews things and gets them out early to users, so I’m sure there’ll be some tweaks. This is a big change for them, and the most recent thing as big as this has been there move into the game console space with XBox. Time will tell.

Salesforce and jQuery Mobile

I wanted to do a project to learn salesforce, but not a trivial hello world style example. I had recently played around with jQuery Mobile, but didn’t do anything significant with it. I decided to put together a basic mobile CRM app. Here’s what the finished app looks like.

contact list screen shot view contact screen shot edit contact screen shot

Salesforce provides a full-featured environment for free to anyone. It takes no time to sign-up for this Developer Edition, and you get access to everything. If you’re just getting started with salesforce, I can’t recommend enough the online tutorials, workbooks, and documentation at developer.force.com.

Accessing the App Data

Our app will contain Contact and Account data. We’ll use Apex Web Service methods to provide the data. We can get all our Contacts with the following:

1
2
3
4
5
6
webService static List<Contact> getContacts() {
  ApexPages.StandardSetController setCon = new ApexPages.StandardSetController(
      Database.getQueryLocator(
          [select id, name, lastname, firstname, title, department, phone, email from Contact]));
    return (List<Contact>)setCon.getRecords();
}

Next we need to call the web service method from the client code. We’ll use the force.com ajax apex javascript libraries to access our data. Add these script references to your page <head> section.

1
2
<script src="/soap/ajax/15.0/connection.js"></script>
<script src="/soap/ajax/15.0/apex.js"></script>  

To call the web service method from JavaScript we use this simple one-liner.

1
var contacts = sforce.apex.execute("MyWebService", "getContacts", {});

Building the UI

Our mobile app UI will be 100% jQuery Mobile, and we can use force.com to provide pure web content. Sites by default provides configurable headers, footers, navigation, etc. that you can apply themes to. We don’t want any of this in our app since we’ll be controlling everything in the UI. To turn off the default stylesheets, header, and navigation elements your apex:page element should set the corresponding attributes, and should look similar to the following:

1
<apex:page showHeader="false" sidebar="false" standardStylesheets="false" contentType="text/html">

Now we’ll add in the jQuery Mobile references.

1
2
3
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0b2/jquery.mobile-1.0b2.min.css" />
<script src="http://code.jquery.com/jquery-1.6.2.min.js"></script>
<script src="http://code.jquery.com/mobile/1.0b2/jquery.mobile-1.0b2.min.js"></script>

The beauty of jQuery Mobile is that all you have to do is markup your html with the correct attributes to get a mobile UI. You don’t need to write any JavaScript. Usually you serve up the jQuery Mobilized html from the server. We want our app to run and function when the device is offline, so we’re going to generate the html at run-time on the client using JavaScript to remove the dependency on the server.

To minimize the amount of html we embed in our JavaScript, we’re going to use jQuery Templates. jQuery Templates allows us to write our html for the UI as we usually would, and to leave placeholders for the pieces we want to replace. Here’s an example of a template used to generate a list page.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script id="object-list-page-template" type="text/x-jquery-tmpl">

<div data-role="page" id="${type}-list-page" data-url='${type}-list-page'>
  <div data-role="header">
      <h1>${pageTitle}</h1>
      <a id='${type}-add-link' data-obj-type='${type}' class='ui-btn-right object-add-link' data-icon="add">Add</a>
  </div> 

  <div data-role="content">
      <ul data-role="listview" id="${type}-list" data-filter="true">
      </ul>
  </div> 

  <div data-role="footer" data-id='footer-nav-bar' data-position="fixed">
      <div data-role="navbar">
          <ul>
              <li><a href="#contact-list-page" data-transition="fade" class="${(type == 'contact') ? 'ui-btn-active' : ''} ui-state-persist">Contacts</a></li>
              <li><a href="#account-list-page" data-transition="fade" class="${(type == 'account') ? 'ui-btn-active' : ''} ui-state-persist">Accounts</a></li>
          </ul>
      </div>
  </div> 
</div> 

</script>

The things wrapped in ${} are replaced with the values. The way we use the template is by calling the $.tmpl method.

1
var $page = $('#object-list-page-template').tmpl(data);

jQuery Templates are very powerful, and really help with the maintainability of your code. Check out the documentation to learn more.

Conclusion

This provides an overview of the core pieces of the solution and the technologies used. If you like to dive in deeper, the complete source is available on github, and the working app is available here (must be viewed in a WebKit based browser).

Automatic Network Location

I bounce back and forth between work and home with a MacBook Pro. At work, I’m behind a firewall, and have to go through a web proxy to get to public internet sites. I have 2 network locations setup, home and work. When I get to work I manually set my location to work, and when I get home, I manually set it to home again.

setting network location

I got tired of remembering to do this so I looked around, and found scselect. scselect is a command line utility that comes with OS X that lets you set your location by name

file.sh
1
scselect "home"

Now all I needed was a way to determine whether I was at work or home and then run scselect with the corresponding location. My work assigned ip address has a set prefix, so I can use that to say I’m at work and anything else would default to home.

file.sh
1
2
# exit code is 0 if on work network and 1 otherwise
ifconfig | grep -i "inet 59.33" > /dev/null

In order to prevent setting the location to the same location we need to find out what the current location is. Running scselect with no arguments displays a list of locations and the active one is marked with an asterisk (*). Here’s my list.

file.sh
1
2
3
4
5
> scselect
Defined sets include: (* == current set)
   575844ED-8466-479C-9567-3F0B7D767EE9   (home)
   3DF4B8B9-2E92-4F61-B684-74E0D0D38DEE   (Automatic)
 * 6064213B-532D-43C9-8941-DC72B6487955   (work)

The output is a bit messy, and we need to parse out the active location.

file.rb
1
2
3
4
5
6
7
8
9
#!/usr/bin/env ruby

# example output: * 6064213B-532D-43C9-8941-DC72B6487955 (work)
output = `scselect 2>&amp;1 | grep ' \\* '`

# parse out the location.  
location = output.scan(/\(.*\)/).first.gsub(/[\(\)]/, "")

# location = work

We now compare the active location with the location our ip address tells us. If different, we call scselect with the new location.

Complete script is available here