mobile

CloudForge Lockout Mobile App

lo-isoThis is an idea I came up with a year ago but didn’t find the time to make a solid pitch to CollabNet management. I’ve recently taken the time to run through some ideation, explorations, and designs.

Whenever the idea of doing a mobile version of CloudForge came up there was usually a rather lukewarm reaction from he product owners and biz dev. The nature of the service simply did not lend itself to a mobile experience. We’re talking about IT in the cloud which takes a lot of serious decision making, analysis, and careful action. Mobile seemed so “on the go” to an organization with roots in SVN.

There was this one use case, though. Something that came out of the Customer Success department calls. There was a case for making it easier to lockout users when a vendor or employee was no longer on the team. This was the one instance when an admin was out to lunch and suddenly needed to rush back and start locking accounts. I thought that maybe a mobile app that did one thing really well would trump an app that tried to address even half of the options available in CloudForge. What if we made an app that just let you manage access permissions for users? This would address a known user pain point, start moving the service into the mobile space, and start getting the users hungry for more mobile access to CloudForge.

lockout-use-case-1 cloudforge-lockout-value

 


Ideation

Pulled out ye olde wipe board and started throwing out ideas. Yes, I keep a wipe board in my bag at all times. I’ve made the mistake of skipping this step in the past. The sooner I start running into issues, the better.


Information Architecture

lockout mind mapLet’s start getting organized on exactly what this app will do. I broke it down into three main actions; lock, unlock, and reset.

Lock = shut out, no getting in, you’re done!
Unlock = Oops! Ok, you’re not so done.
Reset = Locked out until you reset your credentials… just in case someone knows another user’s credentials. It happens.


Wireframes


What you’re looking at here is a version 2.xx. As I ran the initial wireframes through some guerrilla usability I came across some issues. In fact, I ended up running into a menu selection issue on this version. Lemme know if you see it. 😉


Mock Ups

I tend to think of each step in the UXD process as a further exploration of the previous step. As I’m laying out a mockup I’m still open to feature ideas that did not exist in the wireframes. In this case there are four new ideas on the dashboard that did not exist on the wireframes.

explanation

  1. The “New Locks” feature which would let the admin know that someone locked a user outside of this app.
  2. Ability to hide/show the graphs, the ratio numbers (e.g.: 5/20), etc on the slide out controller.
  3. Displaying the percentage of a node as a graph within the node icon itself. The green areas indicate that less than 50% of the total are locked. When the total hits 50% then the graph goes red. I’m thinking that a third state of yellow is not truly helpful.
  4. A flip out filter control set rests at the bottom right. I like to indicate that something can be swiped. Exploration is great but I still prefer clearly marked functionality with this audience, engineers and product managers.
Advertisements

Flojuggler iOS Explorations

Now that we’ve got an MVP ready to submit to the store, it’s time to start iterating on improvements. The app works, it’s intuitive for the majority of testers, and it even has a bell and whistle (singular) but now we need to make some moves to make it a bit more seductive.

Each of the following are non-functional prototypes and are being used to test before narrowing down any viable ideas. Click on each to read a description of the whys and hows.

Using Structural Selectors to avoid Class-itus in HTML5 and CSS3

I’ve been spending some time cleaning up my HTML and CSS in the Flojuggler iOS app. Trying to stay within semantic standards is becoming my latest obsession. I call it an obsession because, like all rules, there’s a time and a place for everything. While it would be great if everything could be super clean all the time, sometimes breaking the rules gets the project to where it needs to be. That said, this example is within the rules. 😉

Here’s a snippet that includes a simple form with an ID of #edit-form. I’m using JQuery Mobile on this project because I like the built in transitions and widgets for HTML5 field types like “number” and “date”.

<form id="edit-form" data-ajax="false">
	<div data-role="fieldcontain">
		<input id="name" type="text" maxlength="25" name="name" placeholder="enter name" value="Unnamed" />
	 </div>
	<div data-role="fieldcontain">
		<label for="cycle-field">How many days between flos?</label>
		<input id="cycle" type="range" max="40" min="1" name="cycle" readonly="readonly" value="30" />
	 </div>
	<div data-role="fieldcontain">
		<label for="long">How many days does the flo last?</label>
		 <input id="long" type="range" max="12" min="1" name="long" readonly="readonly" value="7" />
	 </div>
	<div data-role="fieldcontain">
		<label for="startDate">What is the start date her last flo?</label>
		<input id="startDate" type="date" name="startDate" value="" />
	 </div>
	<input id="thumbnail" type="hidden" name="thumbnail" value="images/thumbnail.svg" />
</form>

Typically I would have placed classes on the first and last field items. This would allow me to target them directly and remove the borders as needed. The thing about that approach is that it requires me place those class assignments into the HTML which just adds to the clutter. Instead I decided to use CSS3 structural selectors instead. This allows me to target the same DOM nodes without adding class assignments to the markup.

#edit-form .ui-field-contain:last-of-type {
    border: none;
}

#edit-form .ui-field-contain:last-of-type .ui-input-text input {
    min-height: 1em !important;
}

#edit-form .ui-field-contain:first-child .ui-input-text {
    width: 12em;
    float: left;
    margin: 0 0 0 10px;
    line-height: 1em;
    padding-top: .4em;
}

Oh… how I wish I had SASS installed. Then I could get rid of those redundant #edit-form tags which are there “just in case”. I’m not sure what the future holds as far as mark up so I want to make sure that these styles are scoped only to this form with the ID of #edit-form. If I had SASS I could do the same by nesting the sub-styles within the #edit-form definition like so…

.ui-field-contain {
    &:last-of-type {
        border: none;
    }
    
    &:last-of-type .ui-input-text input {
        min-height: 1em !important;
    }
    
    &:first-child .ui-input-text {
        width: 12em;
        float: left;
        margin: 0 0 0 10px;
        line-height: 1em;
        padding-top: .8em;
    }
}

Flojuggler iOS Design Update

flo-explorationAs we move ahead with first round BETA testing I’ve started to explore the final aesthetic treatment of the brand, the details of the UI, and some ideas within the UX. Here we see the action buttons revealed after the user swipes downward on a list item. The item itself animates by sliding down, pushing the items below, and making a “click” sound on animation end.

The shadow is applied to the action buttons only. This makes them stand out against the dominating flat design of the item list. The conspicuous dimension of the shadow invites tactile investigation by the user.

The following images are direct grabs from the simulator. These are not mockups. Once the MVP is done I tend to do most of my refinement in live code. If the feature is drastic enough, like the control drawer pictured above, then I’ll mock it up first. That way I can get user feedback before investing in coding hours.

Flo List Screen

You can see how we start with a minimal viable product on the left and iterate toward a more refined UI/UX over sprints. The left facing arrows indicate the ability to swipe left which did not exist in previous versions.

Flo Detail Screen

As time passes we see the new logo, larger numbers, and larger thumbnails in response to usability during previous sprints,

Critiquing the Flojuggler Mobile App Icon

flojuggler-iconFlojuggler keeps track of menstrual cycles for the women you know. It’s not a complex application but the subject matter it deals with can be… sensitive to many. The original site was hugely successful with men and women alike. The majority of women using the site are tracking their own cycles. Now I’m tasked with moving the service from the web into a mobile application using new technology and new branding. At the doorstep of every mobile application’s brand is the app icon. It’s an app’s first and last impression with the user.

As we examine the choices made with the new Flojuggler icon, let’s start with the goals. Every app has some basic goals for an icon (see the Apple Human Interface Guidelines). It should be unique and stand out when alongside other apps. It should be easily related to the application’s function. An effective icon preserves clarity in small or large sizes. The basic droplet shape and primary red color fits all of these goals. Take a look at the home screen section in the icon set below. Even before the image is enlarged the red droplet pops out alongside the others.

icon

Then there’s conceptual goals for this application in particular. These are the fun ones. For this assignment we need a representation that is not too masculine nor too feminine since we have male and female target users. The use of primary red and white is quite unisex. We’re dealing with a very old subject on a very new platform so we don’t want to come off as “old fashioned”. We do not want to come off as ‘kitsch” but do want to come off as “fun”. This is a lifestyle application, not a medical one. We can hint toward the medical nature but don’t want to dwell in it. The simple shape, two tone color combo, and smoothness of the liquid reference execute all of those goals elegantly.

IOS local notifications with Cordova v3+

Andrew Dahlman’s local notifications plug in is a life saver. He’s bridged the gap between the native Objective-C library and your standard JavaScript app sitting in the web view wrapper. I know that he submitted the plug in to the official Phonegap build but I’m not sure if it made it in. It should!

Like many open source projects, the original writer can’t stay on the project forever. When updates to dependencies occur software can become difficult to install/use. Such is the case with this amazingly useful code collection.

So I’m writing this post in order to document some of the issues I ran into along with some solutions. Feel free to comment, correct, or add to the show.

*Note: These are all Objective-C or Xml changes. The Javascript source gave me no issues at all.

1. The plist paradigm has been replaced with config.xml. The read me files refer to a plist file a few times and this can throw some folks off. There was at least one person on the GIT thread that mentioned this.

With the switch to config.xml comes the XML syntax.

<feature name="LocalNotification">
 <param name="ios-package" value="LocalNotification" />
 </feature>

2. The Cordova 2.3.0+ implementation is was missing the badge feature that Andrew had made available in the original Phonegap version. If you find local notifications useful for your app then putting badge numbers on the app icon seems pretty clutch so I added it. Line 16 inserts the badge option while lines 18-19 are for the background and foreground callback features that I personally did not need and left them commented. 


-(void)addNotification:(CDVInvokedUrlCommand*)command {

 NSMutableDictionary *repeatDict = [[NSMutableDictionary alloc] init];
 [repeatDict setObject:[NSNumber numberWithInt:NSDayCalendarUnit ] forKey:@"daily" ];
 [repeatDict setObject:[NSNumber numberWithInt:NSWeekCalendarUnit ] forKey:@"weekly" ];
 [repeatDict setObject:[NSNumber numberWithInt:NSMonthCalendarUnit ] forKey:@"monthly" ];
 [repeatDict setObject:[NSNumber numberWithInt:NSYearCalendarUnit ] forKey:@"yearly" ];
 [repeatDict setObject:[NSNumber numberWithInt:0 ] forKey:@"" ];

 UILocalNotification* notif = [[UILocalNotification alloc] init];

double fireDate = [[command.arguments objectAtIndex:0] doubleValue];
 NSString *alertBody = [command.arguments objectAtIndex:1];
 NSNumber *repeatInterval = [command.arguments objectAtIndex:2];
 NSString *soundName = [command.arguments objectAtIndex:3];
 NSNumber *badge = [command.arguments objectAtIndex:4];
 NSString *notificationId = [command.arguments objectAtIndex:5];
// NSString *bg = [command.arguments objectAtIndex:6];
// NSString *fg = [command.arguments objectAtIndex:7];

 notif.alertBody = ([alertBody isEqualToString:@""])?nil:alertBody;
 notif.fireDate = [NSDate dateWithTimeIntervalSince1970:fireDate];
 notif.repeatInterval = [[repeatDict objectForKey: repeatInterval] intValue];
 notif.soundName = soundName;
 notif.timeZone = [NSTimeZone defaultTimeZone];

 NSDictionary *userDict = [NSDictionary dictionaryWithObjectsAndKeys:
 notificationId , @"notificationId",
 command.callbackId, @"callbackId",
 nil
 ];

 notif.userInfo = userDict;

 [[UIApplication sharedApplication] scheduleLocalNotification:notif];

}

3. For some reason the call to the application object in the actual badge call was not working so I had to call it using the sharedApplication syntax instead.

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
 {

 UIApplicationState state = [application applicationState];
 if (state == UIApplicationStateActive) {
 // WAS RUNNING
 NSLog(@"I was currently active Selino");

 NSString *notCB = [notification.userInfo objectForKey:@"foreground"];
 NSString *notID = [notification.userInfo objectForKey:@"notificationId"];

 NSString * jsCallBack = [NSString
 stringWithFormat:@"%@(%@)", notCB,notID];

 [self.viewController.webView stringByEvaluatingJavaScriptFromString:jsCallBack];

 //application.applicationIconBadgeNumber = 0;
 [UIApplication sharedApplication].applicationIconBadgeNumber = 0;
 }
 else {
 // WAS IN BG
 NSLog(@"I was in the background");

 NSString *notCB = [notification.userInfo objectForKey:@"background"];
 NSString *notID = [notification.userInfo objectForKey:@"notificationId"];

 NSString * jsCallBack = [NSString
 stringWithFormat:@"%@(%@)", notCB,notID];
 [self.viewController.webView stringByEvaluatingJavaScriptFromString:jsCallBack];

 //application.applicationIconBadgeNumber = 0;
 [UIApplication sharedApplication].applicationIconBadgeNumber = 0;
 }
 }

4. Badges were removed from the Cordova plugin properties altogether. I mentioned that earlier. So I added a badge call into the cancel method and added an incrementBadge method.

- (void)cancelAllNotifications:(CDVInvokedUrlCommand*)command {
[[UIApplication sharedApplication] cancelAllLocalNotifications];</pre>
[UIApplication sharedApplication].applicationIconBadgeNumber = 0;
}

- (void)incrementBadge:(NSNotification *)notification {
int num = [UIApplication sharedApplication].applicationIconBadgeNumber;
[UIApplication sharedApplication].applicationIconBadgeNumber = num + 1;
}

100% Apple Development tools?!

Yes, it’s true! I know you think I’m mad for even considering using anything but Chrome with SublimeText2 or 3 or whatever. After all, Chrome has dominance over the rest in browser share (something like 80% last I read) and has some rock solid dev tools built in while FireFox still uses Firebug to do most dev’s heavy lifting very well. TextMate was all the rage when Rails was king but this is the internet business and kings fall fast around here. Now anyone not using Sublime Text is labeled a heretic. Unless of course you’re using vi in a terminal and then you’re just “keeping it real”.

Xcode and iPhone Simulator Setup

This is my general setup when I’m working on an iPhone app. These two apps cannot be separated.

One of my projects is a mobile app using Phonegap for IOS. Developing for the iPhone is great fun but it does have some serious drawbacks. Namely, Xcode and Simulator. To make sure that your app works on an iPhone you’ll need to use the Simulator application provided in the Apple Developer SDK. Apple is known for three things; Steve Jobs, great looking products, and insanely overbearing control of all aspects of their realm. You want to use a Mac? Better use OSX. You want to charge your phone? Better get the special connector. You want to develop apps for OSX or IOS? You better use Xcode and Safari alongside your standard toolset. Sigh.

Cursed was I! Cursed, I say. Well… not so much.

Safari Developer Tools

A real Javascript console in Safari? Yep, but it’s still a little buggy.

Turns out that Safari now has a full set of developer tools built in! Has a lot of the look and feel of Chrome and Firebug and all of the functionality. Dom inspection, xpath trees, resource lists, network activity, and… wait for it… a full console. Not that big a deal until you realize that means no more bouncing from browser to browser to check my JS in an app. I can load up in Safari and work “as usual”. Frankly, I think Safari is actually faster on OSX than Chrome. That’s so Apple.

So far so good but I was still stuck with Xcode giving me CSS files with no code coloring or hinting. When I was doing Objective-C it had more hinting than I could stand! I had to stop the thing from writing my code for me. With HTML, CSS3, and JS it seemed a bit lacking. So I did some digging. It turns out that you can manually set a document to the correct code hinting and coloring! From the top menu go to Editor > Syntax Coloring > [doc type]. Xcode seems to not be smart enough to apply the rules to all files with the .css mime type. I had to manually set each file that was not recognized.

Now I have a full on IDE that opens my Phonegap app in Safari (Open in External Editor command) so I can develop my app outside of Simulator with full browser dev tools and the same Javascript engine that the actual app will run. If it works in Safari, it’ll work on the iPhone web view.

Not the dreamiest situation but it’s way better than it used to be.