After creating a new Poly project,
let’s create a counter app as a gentle introduction to Poly.
In this guide, we will use TypeScript to create the app, using the poly and the poly-widgets TypeScript library.
The Main File
Before writing any code, let’s have a look at the main file src/main.ts.
When building the binary of the portable layer, this main file is fed into the compiler.
Then, the compiler produces a single binary that is spawned by the native layer when running the app,
which runs the main function defined in the main file. Now, let’s go through the main function.
The Context Object
The first point of interest is the following snippet
The createApplication function, exported by poly, creates a context object that stores all the runtime information of the application,
such as created views and registered callbacks.
Pass this context to any Poly API that asks for a context object.
An instance of StdioMessageChannel is used as the channel between the portable layer and the native layer for exchanging messages.
The Application Instance
After creating the context object, it is used to start the application:
The runApplication function, also exported by poly,
returns a Promise that will awaited at the end of the main function to keep the application alive.
Application Logic
In between awaiting the instance and the call to runApplication is where the application logic resides,
such as drawing the UI and creating windows.
In this case of creating the counter app, this is where the UI of the counter and the logic of the counter sits.
By default, the main function creates an empty window that has the application name as its title:
The tag is a handle to the window.
It is useful, for example, when specifying where to display the created widgets, which we will get into later on this page.
It must be unique amongst all the windows created by the application.
Keeping the Application Alive
Finally, this line:
keeps the application run loop alive.
Making the Counter UI
The counter UI consists of three elements: the current count, the increment button, and the decrement button, all inside a column in order.
Let’s define a class called CounterScreen that encapsulates the UI code and the logic of manipulating and keeping track of the count. Create a new file called counter-screen.ts next to main.ts:
CounterScreen subclasses WidgetController, which is an abstract class that defines the interface
for a class that controls and holds references to widgets.
In this case, CounterScreen will hold a reference to the counter text label because we will need it to update its content.
Defining the UI tree
poly-widgets exports a variety of widgets that can be composed together to form the UI.
Let’s first create a Text to display the current count.
Here, we are creating a new instance of Text and settings its initial content to the initial count (this.count) which is 0.
We are also storing a reference to the Text under this.countText so that we can use it later when we need to update it.
Let’s create the increment and the decrement buttons, as well as defining the callbacks when they are clicked:
We want to put the count text and the buttons in a column, so we are going to use the Column widget:
To center everything in the window, we are going to wrap the column with a Center widget:
We need to let Poly know the root view of our screen (which is a WidgetController),
so we also need to implement the widget(): PolyWidget method from WidgetController.
Modifying the Counter
When the increment button is clicked, the counter needs to be incremented and the count text updated. We can do that in the incrementCounter method:
Same for the decrement button:
When updating any widget in Poly, the update method needs to be called.
It accepts a callback in which updates on the widget should be done.
The update method lets Poly know that the widget is updated and needs to be redrawn.
Now, when the increment button is clicked, incrementCounter is called, which increases the count variable by one and updates the counter text with the new count.
When the decrement button is clicked, decrementCounter is called, which decreases the count variable by one and updates the counter text accordingly.
Showing the Counter Screen
Now that we have created the counter screen, let’s import it in the main file and display it:
Running the Application
We have finished creating the counter! Before running the application, we need to compile the TypeScript code first:
This generates a binary named bundle in <project-name>/build:
Now, open the .xcodeproj file in the macOS folder in XCode. Wait for XCode to finish building the project, then hit the Run button.
That’s it! You have successfully created your first Poly application with TypeScript.