Blog

Later Ctrl + ↑

Use without internet or use other network

Sometimes when you connect to a Wi-Fi network, a login window pops up, but it remains blank for a long time. So you give up and press Cancel. And you end up here:

Use without internet or use other network

This is the most frustrating menu in iOS. What am I supposed to do? First of all, I have just pressed Cancel and the system has ignored me. Instead of cancelling the process, it decided it should bother me with some additional questions.

As if it wasn’t bad enough already, the choice I am presented with makes no sense to me. There is no “Just Cancel” option. The Cancel button you see on the bottom will just Cancel the cancellation process I’ve initiated and get me back to the blank window. I don’t want to “Use Without Internet”: I need the Internet. I don’t want to “Use Other Network”: this is the only network available here. I just want to Cancel. Please? Just fucking leave me on 3G.

Jouele 2.0

Jouele 2.0

Three years ago I made Jouele, a good audio player for the web.

Eugene Lazarev has made version 2.0. The player has dropped the skeuomorphic look and got even nicer. It is now easier to customize the colours. The new version has dynamic initialisation, and is a jQuery plugin with an API (these are presumably good things). I have installed it on my website.

Related:

How accidental promises hurt reputation

With Alex Babaev we have a policy of no comments about the future of Ångström. We want the freedom of being able to change our minds any time. And we don’t want to look like jerks who don’t keep promises. So whenever somebody asks about our plans or requests a feature, we just thank them and explain that we do not pre-announce things.

About a year ago I got this email message from a user:

Best converter ever, I immediately deleted all the others, yours has the best UI. Really nice would be a German translation. Can I help you with that? Should be pretty easy, just give me a list with variables.

We had Ångström 1.1 in the App Store and were waiting for 1.2 to get approved. We also had the German translation done by that moment and we were planning to ship it in version 1.3. So something broke in my head that day and I responded:

We’ve started the work on German translation recently. We cannot promise anything so far, but it is likely to be added in an update (not in 1.2 though). Thank you for being ready to help, we will drop you a line if we have questions.

And thank you for the kind words!

I didn’t say it had been done, I said we’d started the work on it. I even said “We cannot promise anything”! But that’s not how things work. As I learned later, I promised to ship German translation in 1.3 in that email. In March, I got another message from that same person:

I was a little sad, there was no German translation in the 1.3 update.

I, too, was sad. Why didn’t we ship German in 1.3? While it was ready for version 1.2, the translation became a little bit obsolete when we finished work on 1.3. We added many new features which were not covered by the translation we had. We could delay the release of 1.3 to update the translation, but we decided that it was more important to ship the actual features. And so we did.

In versions 1.4 and 1.5 Ångström and our German translation further diverged. We just couldn’t find time to update it, because other features felt more important. In August, I got another message from the person:

A year ago I asked about German translation. I even offered my help. You stated, your team already started working on it, so I bought the damn thing. A year later… nothing happened. Thanks for lying to me.

This was not a message I enjoyed reading. I almost started a reply saying that actually I had not promised anything. So technically I did not lie! But we are not in court, and what matters is not what I wrote in that first message, but what my words felt like. And they really felt like we were going to add the German translation in 1.3.

Ångström in German

We finally shipped German with version 1.6 a week ago, more than a year after that letter where I promised in it 1.3. I am sorry about that.

Don’t repeat my mistake. Don’t say anything about the future of your product except that you don’t want to say anything about it.

Ångström: onboarding and light redesign

We’ve updated Ångström to version 1.6.

First, we’ve lightly redesigned the app. The numeric keyboard got full width and there’s now a gear icon to go to the About screen (few people could find it before). Everything looks twice as cool now, especially if you have iOS 9 with the San Francisco font. Before and now:

Ångström 1.6

Check out how the gear spins when you pull the About screen from the left with your finger.

Better onboarding. We explain to the new users what they are supposed to do:

Ångström 1.6

Before, some people did not understand that they could just type what they thought, and Ångström would get it. They were trained by other converters to first set stuff up in various menus, but could not find anything like that in Ångström.

When converting local time we now find cities by timezone codes (like PST or CET). New units: gallon per minute, gallon per hour, kilopascal, megapascal, technical atmosphere and millimetre of water. We also now understand the words “quid” and “buck”.

Improved voice recognition, much improved VoiceOver support. Added German localization (special thanks to Pascal Kreil and Dmitri Evmenov).

If you are not yet using Ångström, you should:

Download in the App Store for free

The app is free, but you can buy an extended unit pack with an In-App Purchase. Even if you don’t really need it, you can buy it as a way to say that you like Ångström.

iOS 9 will get released soon and everyone will be able to enjoy the San Francisco font.

Emerge.js with a new spinner and scrolling support

In 2013, I’ve released Emerge.js, a framework for coordinated page loading:

Normally, when a complex web page is loading, images appear in random order, causing unpleasant flashing. To replace it with nice and coordinated animations, programming is required. Emerge.js simplifies the task by removing the need to write any JavaScript code. The framework uses a declarative approach, where you specify a desired behaviour for each element and do not think about the implementation.

See also the introductory blog post. I’ve since updated it with new features.

Spinner stuff

In version 1.1 I’ve added a built-in loading spinner. Emerge.js no longer requires spin.js for that. But you can use a custom spinner, including spin.js, if you like.

As before, to display a spinner while an element loads, use data-spin="true". Use the new attributes data-spin-size, data-spin-color, data-spin-direction to control the appearance of the spinner (see documentation on the Emerge.js’s page).

To use another indicator (i.e. one of the nice ones by Sam Herbert) just wrap it into a named div and tell Emerge.js to use the contents of the div as an indicator:

<div id="cool-spinner" style="display: none">
  <svg> ... </svg>
</div>

<div class="emerge" data-spin-element="cool-spinner">
  <!-- while this loads, the cool spinner will be displayed -->
</div>

To use spin.js, make it run inside your div and align as necessary:

<script src="/path/to/spin.js"></script>

  ...

<div id="spinjs-spinner" style="display: none">
  <div style="position: absolute; left: 50%; top: 50%; margin: -8px"></div>
</div>

<script>
  var spinner = new Spinner ({
    lines: 12,
    length: 4,
    width: 2,
    radius: 8,
    corners: 0,
    rotate: 0,
    color: 'rgba(96, 96, 96, .75)',
    hwaccel: true
  })
  spinner.spin ($ ('#spinjs-spinner div')[0])
</script>

  ...

<div class="emerge" data-spin-element="spinjs-spinner">
  <!-- while this loads, spin.js will be displayed -->
</div>

Scrolling stuff

In Version 1.2 with the new data-expose attribute you can make an element emerge only when the user scrolls enough for it to get into view.

<div class="emerge" data-expose="true">
  <!-- this will emerge only when within view -->
</div>

Of course you can combine it with other attributes and effects. This div will emerge with a zoom effect in a quarter second after the users scrolls enough for it to become visible:

<div class="emerge" data-effect="zoom" data-hold="250" data-expose="true">
  <!-- this will emerge quickly after getting into view -->
</div>

For an example, see my Projects page. The data-hold value varies slightly between elements there to add a nice randomness effect.

Update for free

If you’ve bought Emerge.js, you get the updates for free. Drop me a line if you have any questions.

Jony Ive on blunt criticism

I am listening to an audiobook on Steve Jobs. A quote about blunt criticism:

That’s why “That’s shit!” was as common response from Steve as a pointed question or a thoughtful discussion. He wanted smart answers and he didn’t want to waste time on niceties when it was simpler to be clear, no matter how critical his response.

“The reason you sugarcoat things is that you don’t want anyone to think you are an asshole. So, that’s vanity”, explains Jony Ive […] “As a design chief, I was on a receiving end of Steve’s blunt criticisms as much as anyone”. Whenever he felt abused he would tell himself that someone who sugarcoats his true opinions might not really even be all that concerned about the other person’s feelings, he just doesn’t want to appear to be a jerk. But if he really cared about the work, he would be less vain and would talk directly about the work.

That’s the way Steve was. That’s why he’d say “That’s shit!”, but then the next day or the next after he also would just as likely come back saying, “Jony, I’ve been thinking a lot about what you’ve showed me, and I think it’s very interesting after all. Let’s talk about it some more”.

Steve put it this way: “You hire people who are better than you are at certain things and then make sure they know that they need to tell you when you’re wrong”.

Earlier Ctrl + ↓