Making an iOS custom dialer app with Shortcuts and elm-spa
Introduction
Many moons ago I wrote an Odorik iOS app that allowed comfortably setting up a callback on my VOIP/GSM operator of choice – Odorik.
But since Apple Developer membership isn’t exactly free (and the app was written in Rubymotion, which switched to subscription model), it was uneconomical to keep the app updated and in the AppStore. Last year I pulled a plug on it.
But turns out that I would still like to easily setup callbacks! And so would others, that miss it (I’ve got several emails).
Spoiler alert: This post documents the journey to a viable replacement built on top of iOS Shortcuts app (by Apple) and elm-spa.
Problem statement
I, as a user, want to select a phone number from one of my iPhone’s contacts, and have an app setup a callback – with that number as a target – for me.
For those of you who don’t know, callback is basically a two-legged phone call. Odorik’s PBX first calls one number, then another, and connects them together.
Why is that useful? Say you reside in Switzerland, but have a lot of people to call in the Czech republic. Outgoing call rate from your GSM operator is horrendous1. So you have Odorik dial out to your phone, and connect you internally with the destination number. Both legs combined add up to a fraction of the normal (per minute) cost.
The easy parts
Odorik already publishes their API. And a monkey
with a screwdriver2 can do an outgoing HTTP POST
call, so
setup a callback for me is trivial.
The hard parts
-
The select a phone number from one of my iPhone’s contacts task together with integration used to be tough. Actually, it used to be impossible without a native app.
-
If I’m to deploy a solution, it better be maintenance-free, and without the need to store user’s data or use cookies (I don’t want responsibility and privacy nightmares).
-
And while I’m at it, I suck at frontend programming, and always wanted to try Elm. Ideally on a real world project.
-
And since elm-ui promises web apps without a single line of HTML/CSS, let’s do that.
-
And because single page apps are awesome, let’s add elm-spa to the mix.
Architecture
Let’s start with one of my world-famous arch diagrams:
Architecture implications
In order to avoid cookies and storing any user data in general3, I had to find a way to make use of client javascript.
Fortunately, localStorage
is a thing. So I can store some amounts of data
directly on the iPhone. And call the Odorik API also directly from the iPhone.
Thus the webapp simply serves as a (client) software delivery mechanism.
In order to avoid passing the contact data, I resorted to using the #hash
part of URL. As hashes are not part of HTTP requests. They are only processed
in the browser.
With those two, the data privacy issue is solved4.
Shortcuts app – selecting the contact & forwarding
Apple’s Shortcuts app5 is one of the iOS’s best kept secrets. By that I mean that it’s severely underutilized (as far as I can tell), apart from a few superusers.
And it’s a shame. Because apart from the drawback of visual workflow creation, it is the single best “glue” you can find for iOS.
To Script the necessary workflow, I basically:
- Asked to select a contact
- Grabbed name, label, number
- Encoded as json
- base64encoded that
- Called out to the webapp (
https://odorik.wejn.org/callback#<datahere>
)
Check this out:
workflow thumbnail; click for full-size version
Granted, I also added an extra feature where numbers with a certain
(customizable) prefix (+41
for me, skip
by default) cause the workflow to
dial the number directly instead of setting up callback. That way I can use one
app for all my calling needs.
The shortcut workflow is downloadable here if you want to poke around.
To view/install it, you need to visit System settings → Shortcuts → Allow Untrusted Shortcuts.
After installation it can be also added to the Home screen, by tapping the three dots (visible in the screenshot above) and selecting Add to Home screen from the sharing sheet (modal menu).
The web app
How I wish I could say “oh, it was super easy, barely an inconvenience”.
That would be lying, though.
I kept banging my head against the wall for a few days. Fortunately, I’m unaware of any lasting brain damage as a result. ;)
I think that’s in part thanks to Alex Korban’s books
(Practical Elm and
elm-ui: The CSS Escape Plan), which
cleared up some sticky points for me. (Http
tasks, for one)
Those resources, coupled with a whole lot of web-searching allowed me to go from zero to functional in… sigh… a more than a few evenings.
If you’re really interested in particulars6, look at the commit history.
Because I’m unsure how to put my experience to words.
I’ll touch on a few points:
-
The entire time I had a feeling that dropping down to native html elements (and javascript) would cut the development time by an order of magnitude.
-
The lack of perceived basics (unordered list, combo box, …) is a drag
-
The need to add a
Msg
andupdate
clause for every non-static action quickly gets old -
I have yet to figure out how to do an (IMHO) trivial show this, and 3 seconds later, show that.
In the end, it could be the noob in me talking. :-)
To conclude, check the source if curious.
Or the deployed website; demo credentials included.
Final words
Here it is. An Shortcut workflow and a single page app. To get callbacks through Odorik working.
I’m happy with the result, even if there’s ample room for improvement.
Can’t wait to hear what other iOS users of odorik.cz think.
Meta: I’ll continue poking both Shortcuts but also elm in further posts (after all, the Yamaha Soundbar needs a proper “UI”).
-
Hello, Sunrise. ↩
-
That would be me. ↩
-
It would be a privacy nightmare to process someone’s contacts with phone numbers! ↩
-
Inevitably someone will stop by to tell me that I (or an attacker) could deploy a malicious app that steals all the contact data. Yes, you’re right. If that a concern, please deploy your own instance of it. It ain’t a rocket science. ↩
-
In other words, knowing what it takes for a total elm noob to write an elm web app that compiles. [Nobody dares to say anything about “idiomatic” here.] ↩