- Products
- Solutions Use casesBy industry
- Developers
- Resources Connect
- Pricing
Do you know what HyperCard is? What about Decker? If you’re unfamiliar with any of those two, you’re missing a lot, but no worries, in this post we’re going to build an old-fashioned agenda using Decker (HyperCard) and the Ruby Nylas APIs.
HyperCard combines a flat-file database, a graphical and flexible interface with an easy-to-use programming language called HyperTalk. It was released in 1987 (35 years ago) and it was the first successful hypermedia system. It was used to make applications, games, interactive guides and more:
Decker is a multimedia platform for creating and sharing interactive documents, with sound, images, hypertext, and scripted behaviour. Its programming language is called Lil.
Based on HyperCard, Decker retains the old-fashioned look and feel of the classic MacOS.
If you already have the Nylas Ruby SDK installed and your Ruby environment is configured, then continue reading this blog.
Otherwise, I recommend reading the post How to Send Emails with the Nylas Ruby SDK to understand the setup basics.
We’re going to use the Nylas Ruby APIs to fetch our contacts, and then create a .deck file that can be opened in Decker. As we’re going to use profile images, we’re going to download them and use Lilt (A command-line interface for Lil, Decker’s scripting language) to convert them into an encoded string that Decker will interpret as a pixelated, black-and-white image.
Here are a couple of screenshots so you can see what I mean:
This is the main screen. Here we can press Enter to start browsing our contacts.
If you’re into wrestling, and you’re old enough, you should know Hulk.
You can see here that they are coming from my contacts:
The best and easiest way to install Decker is to download (you can pay to support the developer) the .zip file for your operating system from here:
First, we need to install the Image Magick package for our operating system here, or we can simply use brew:
$ brew install imagemagick
And then install the MiniMagick gem:
$ gem install mini_magick
In order to install Lilt, we need to download the source code and then run the following command:
$ make lilt && make install
We’re going to create a folder and call it Address_Book (feel free to call it something else). Inside, create a file called address_book.rb with the following source code (The deckbuilder section has been reduced to save space, you can check the complete source code here):
# frozen_string_literal: true # Import your dependencies require 'nylas' require 'dotenv/load' require 'mini_magick' # Initialize your Nylas API client nylas = Nylas::API.new( app_id: ENV['CLIENT_ID'], app_secret: ENV['CLIENT_SECRET'], access_token: ENV['ACCESS_TOKEN'] ) deck_source = '{deck}' + "\n" + 'version:1' + "\n" + 'card:0' + "\n" + 'size:[512,342]' + "\n" + 'name:"contacts.deck"' + "\n\n" + '{fonts}' + "\n" + 'deckbuilder:"%%FNT0GCA"' + "\n\n" + '{card:home}' + "\n" + '{widgets}' + "\n" + 'Title:{"type":"field","size":[149,38],"pos":[177,90],"font":"deckbuilder", "style":"plain","align":"center","value":"Contacts"}' + "\n" + 'enter:{"type":"button","size": [60,20],"pos":[222,213],"script":"home.0","text":"Enter"}' + "\n" + 'field1:{"type":"field", "size":[149,49],"pos":[177,140],"font":"menu","style":"plain","align":"center", "value":"An address book\ncreated using Decker and Nylas"}' + "\n\n" + '{script:home.0}' + "\n" + 'on click do' + "\n" + ' go["Next" "SlideDown"]' + "\n" + 'end' + "\n" + '{end}' + "\n\n" # Fetch contacts contacts = nylas.contacts.where(source: "address_book") # Needed to call scripts first_card = contacts[0].given_name + contacts[0].surname.gsub(/\s.*/,'') + '.0' first_card_script = contacts[0].given_name + contacts[0].surname.gsub(/\s.*/,'') + '.1' counter = 0 # Loop through all contacts contacts.each do |contact| counter = counter + 1 # Get the profile picture picture = contact.picture file_name = 'profile.png' # Save the profile picture File.open(file_name,"wb") do |f| f.write File.open(picture, 'rb') {|file| file.read } end # Use MiniMagick to resize and reformat the image image = MiniMagick::Image.open("profile.png") image.resize "100x100" image.format "gif" image.write "profile.gif" # Call the Lil script cmd = `lilt encode.lil` # Make sure nothing is empty if(contact.nickname == nil) contact.nickname = '' end if(contact.birthday == nil) contact.birthday = '' end if(contact.emails[0].email == nil) contact.emails[0].email = '' end # Generate the information for the .deck file deck_source += '{card:' + contact.given_name + contact.surname.gsub(/\s.*/,'') + '}' + "\n" + '{widgets}' + "\n" + 'profile:{"type":"canvas","size":[100,100], "pos":[30,90],"show":"transparent","border":0,"image":"' + cmd + '","scale":1}' + "\n" + 'field1:{"type":"field","size":[78,20],"pos":[184,76],"font":"menu", "style":"plain","value":"Given name:"}' + "\n" + 'givenname:{"type":"field", "size":[173,20],"pos":[275,76],"font":"mono","style":"plain","align":"center", "value":"' + contact.given_name + '"}' + "\n" + 'field2:{"type":"field", "size":[78,20],"pos":[184,104],"font":"menu","style":"plain","value":"Nickname:"}' + "\n" + 'nickname:{"type":"field","size":[174,20],"pos":[274,103],"font":"mono", "style":"plain","align":"center","value":"' + contact.nickname + '"}' + "\n" + 'field3:{"type":"field","size":[78,20],"pos":[184,131],"font":"menu", "style":"plain","value":"Surname:"}' + "\n" + 'surname:{"type":"field", "size":[174,20],"pos":[274,130],"font":"mono","style":"plain","align":"center", "value":"' + contact.surname + '"}' + "\n" + 'field4:{"type":"field", "size":[78,20],"pos":[184,158],"font":"menu","style":"plain","value":"Birthday:"}' + "\n" + 'birthday:{"type":"field","size":[175,20],"pos":[274,157],"font":"mono", "style":"plain","align":"center","value":"' + contact.birthday + '"}' + "\n" + 'field5:{"type":"field","size":[78,20],"pos":[184,185],"font":"menu","style":"plain", "value":"Email:"}' + "\n" +'email:{"type":"field","size":[176,20],"pos":[274,184], "font":"mono","style":"plain","align":"center","value":"' + contact.emails[0].email + '"}' + "\n" + 'Next:{"type":"button","size":[60,20],"pos":[258,305], "script":"home.0","text":"Next"}' + "\n" + 'Previous:{"type":"button","size":[60,20], "pos":[182,305],"script":"' + first_card_script + '","text":"Previous"}' + "\n\n" + '{script:' + first_card_script + '}' + "\n" + 'on click do' + "\n" + ' go["Prev" "SlideDown"]' + "\n" + 'end' + "\n" + '{end}' + "\n\n" if(counter == 1) deck_source += '{script:' + first_card + '}' + "\n" + 'on view do' + "\n" + ' go[0]' + "\n" + 'end' + "\n" + '{end}' + "\n\n" end end # Write the source code for the .deck file File.open("addressbook.deck", "wb") { |f| f.puts "#{deck_source}" }
Before we can run this, we need to create a Lil application to be opened by Lilt, we will call it encode.lil:
print[read["profile.gif" "gray"].transform["dither"].encoded]
This script will make the image grayscale, pixelate it and then return the encoded string.
In order to run our application, we need to type the following on a terminal screen:
$ ruby address_book.rb
And then open the generated addressbook.deck on Decker.
We just build an old-fashioned agenda using Decker (HyperCard) and Ruby.
Don’t miss the action, join our LiveStream Coding with Nylas:
If you want to learn more about the Nylas Contacts API, please visit our documentation Contacts API Overview.
Blag aka Alvaro Tejada Galindo is a Senior Developer Advocate at Nylas. He loves learning about programming and sharing knowledge with the community. When he’s not coding, he’s spending time with his wife, daughter and son. He loves Punk Music and reading all sorts of books.