Linux Format

Build Proton apps

Mats Tage Axelsson takes you through creating a desktop applicatio­n using Proton Native, the React way to the desktop.

- Mats Tage Axelsson keeps fighting the tide, showing you what even he can do using Linux to make the world a better place and improve his own life in the process.

Mats Tage Axelsson takes you through creating a desktop applicatio­n using Proton, the React way to the desktop.

You may not be surprised that some developers have criticised Electron (see tutorials LXF256), mostly regarding the memory usage of its final binaries. The initial binary is over 100MB, because a major chunk of code from Chrome is embedded. When you create a small piece of code, this is a horrible waste. With Proton Native the binary is compiled with the bare essentials, making the binary a few kilobytes in size. That’s a very big win for small utilities.

Until now Proton Native hasn’t been in much use with bigger projects. However, it may become popular thanks to the potential for more efficient and smaller binaries compared to Electron. Since it supports Node.js, developers can create pretty much everything that they can with Electron.

Environmen­t and compilers

Under the bonnet, Proton Native uses libgtk3-dev, build-essential, python2 and pkg-config for its compiling, so make sure they are installed.

$ sudo apt install libgtk3-dev build-essential python2 pkg-config

Now you can compile the package you are about to make. This is a Node.js package that you can install using npm or npx. At the time of writing, this package needs an old Node.js version – 10.15.3 works. To ensure that your applicatio­ns work, make sure each project uses the correct version and follow up as you go.

Proton Native uses auto-gyp to compile to the local binaries. Auto-gyp works with gyp and nbind to choose the compiler and its options, making it possible to compile your code in C++. For your case, you need to keep track of developmen­ts so you can upgrade to a newer Node.js and move to Python 3, since Python 2’s End Of Life status is 2020.

Start by creating a directory for all your projects. If you use the automatic install method, the script will create a directory for your project and install all Node.js software you need. However, it will fail. This is where you need to choose the old Node.js. Install nvm globally. $ sudo npm install -g nvm

Now you can create a file for setting another Node.js for your applicatio­n. Put a .nvmrc file in your project directory and fill in the version value v10.15.3 . Until the project is upgraded you will still get a lot of warnings about deprecated functions in the V8 engine of Chrome.

If you want to be more bleeding-edge, you can use the Github repository for your projects. If you can solve it yourself, make a branch and refer to that one. Branches are reached with a hashtag ‘#’. Move into your project directory, remove node_modules and reinstall.

$ cd

$ rm -rf node_nodules/

$ npm install

You will still get a lot of warnings but it will go through and you can try out your template project.

If this seems complicate­d, you can also create the library and add the files manually. Use the Proton Native install script while in your project directory. Do this after you have installed nvm and set the .nvmrc file as described earlier.

$ npm i -S Proton Native

After the script runs, you will have the node_ modules directory and package-lock.json as well as the .nvmrc file. You need to add two more files: .babelrc and package.json. Add this to .babelrc:

{

“presets”: [

“env”,

“stage-0”,

“react”

} This specifies the Babel functions and you can see that it runs in react mode. Babel is a Javascript compiler that will make sure your final result is backwards-compatible and correctly formatted. This includes handling the JSX syntax; without it you would have to write much more complex code. You can now install Babel itself.

$ npm install --save-dev babel-cli babel-preset-env babel-preset-stage-0 babel-preset-react

Next, in package.json you need to define that babel runs your main Javascript file, in this code: index.js. scripts: {

“start”: “babel-node index.js” }

With this method, you are also missing the template index.js file. However, it is very small, so create the file and add: import React, { Component } from ‘react’; // import from react import fs from’fs’; import { render, Window, App, } from ‘Proton Native’; // import the Proton Native components

class example extends Component { render() { // all Components must have a render method return (

// you must always include App around everything

{/* all your other components go here*/}

);

}

} render(); // render your main component

With those files in place, you can run your test project like this:

$ npm run start

The result is a little window with the heading “Proton Native Rocks!’ You are now ready to take on the challenge of creating your own applicatio­n, so let’s have a look at doing that.

Your code is going to be in Javascript and React, so using your favourite IDE or editor is your best bet. Obviously Emacs is best. Proton Native also requires g++, but you have installed all these at the beginning of the tutorial.

When you have written a full applicatio­n, you can have Proton Native create binaries that you host somewhere on the web. This function actually uses electron-package but makes sure not to include the entire binary from Chrome, as Electron does.

In this project, you will upgrade an existing example from the proton repository. The project you start with is Notepad, so download all of Proton Native from https://github.com/kusti8/proton Native. In the examples, you can find a box statement; copy it into your code, add Box and Textinput to your import

statement and let’s get started.

This code creates a box that you cannot see, but it is inside the applicatio­n. As you can guess from the code, you can input text into the box. The first statement is

onchange ; as you might guess, this statement runs the function when the text changes.

Your text is in the state of the app function. This means it updates the state at every letter you write, which could be a problem – but React has solutions for this. You may also want to save the notes as a file, so let’s add that too. To do this, add fs to your import and

Dialog to the Proton Native import. The same code also includes shouldcomp­onentupdat­e() – this function updates the component when the state or props change. In the Notepad applicatio­n, this happens every time you enter text.

Now, let’s try something else! Make an input box that takes radio buttons and saves the value to state and a file. You can copy the code this time from the examples in the documents for Proton Native on Github. This example has two options and there’s no way to know which is selected. Change the code like below in index.js for Lovemytask­s.

class Lovemytask­s extends Component {

state = { text: ‘’, project: ‘’ }; ...

this.setstate( {project} )}>

project 1

Radiobutto­ns.item> project 2

Radiobutto­ns.item>

This code adds how the applicatio­n reacts when an item has been selected. For it to work, you must add project to the state at the top of the class. To style the buttons, you need some CSS. In Proton Native, this is achieved with the built-in functions.

Make a grid

When you just add buttons in your code, you can change very few aspects of where the parts go. Your components will appear somewhere on the screen without any special order. In this case, you can use Grid. Grid encapsulat­es your graphical elements, giving you the opportunit­y to set them on the screen where you want them. When you have done this, every component has new values they can use to place them in relation to each other. The Radiobutto­ns code changes like the code below.

this.setstate( {project} )} row ={0} column = {1} expand={{h:false, v:false}}> project 1 project 2 {console.log(this.state)};

The values are row , column and expand . The first two you use as expected to make a grid. The expand value denotes if the component is allowed to expand in the direction that you mention. Make sure you use an object – the double curly braces are easy to forget. There are also other values available, experiment with them to get to know them.

To be able to save your data to a file, you need to add some code to the file save and open options.

index.js (File menu)

… save() { const filename = Dialog(‘save’); if (filename) { let data = (Json.stringify(this.state)); console.log(data); fs.writefiles­ync(filename, data ); } } open() { const filename = Dialog(‘open’); if (filename) { let data = fs.readfilesy­nc(filename); // Data is a string, parsing with JSON); this.setstate(json.parse(data)); // Make interface update this.forceupdat­e(); console.log(this.state); } }

Now you have the data saved as a string which is saved to whatever file you choose to use. When you open the file, you only get the first part of the string back into the applicatio­n. The chosen project is not transferre­d since setstate does not read it out.

The functions we want to use are Json.stringify and Json.parse . They are each other’s counterpar­ts – stringify makes a string of a Javascript object. In our code, we do that when we want to save our file. Next, when we want to load the file back in, we parse the JSON file. In production code, you will need to handle files that do not contain JSON, but that is a bigger issue.

Now we have to make the interface update after we load it in. We make sure of this with the forceupdat­e

function of our main applicatio­n. When you start getting serious, your code will start looking messy. It will become hard to read and each time you have a new idea, it is hard to find your way around the code. To solve this, we can use components.

Make a component

When you want to make a component, you will use the object-orientated power of Javascript. In the file, you define a class and export it at the end of the file. You can export by name if you want several modules, or use the default keyword to add it to your import. Combining this with React, you get a method to add JSX to your

code. The best way to understand this is to move out code you have already written. So start with moving out the menu to a separate file. This makes your main file cleaner. Create Mainmenu.js and enter this code: import React, { Component } from ‘react’; import {

Menu,

} from ‘Proton Native’;

export default class Mainmenu extends Component { render() { return(

Open

Save

);

} }

The observant reader will notice that the onclick statement has changed to contain only the name of the code, not the entire code. In the index.js file, you now need to change the top of the class. Add a constructo­r so you can refer to the imported class:

... import Mainmenu from ‘./Components/mainmenu.js’ ... class Lovemytask­s extends Component { constructo­r(props) { super(props); this.state ={ text: ‘’, project: ‘’, }; this.save = this.save.bind(this); this.open = this.open.bind(this); }

The key difference here is that the ‘state’ needs to be part of the constructo­r and that you bind the code that you will use from the imported code. You also need to throw out the menu code inside your tag.

// you must include App for everything

/>

As you can see, the menu is now much smaller, making it easier to read the code. If you need to change the menu, start in the Mainmenu.js file and tweak the index.js file.

The Proton Native project tries to make it easy to create desktop applicatio­ns using Javascript and React. In contrast to Electron, it does not include the

Chromium browser to achieve this. Instead, it uses other projects to compile to native components using Qt. Qt is not delivered on all platforms but it uses the underlying system, avoiding large binaries for small tasks. In short, Proton Native is an exciting project with a bright future but it is currently lacking some stability.

 ??  ?? Coding in React looks very similar but be aware that certain things do not work the same due to limitation­s still in underlying libraries.
Coding in React looks very similar but be aware that certain things do not work the same due to limitation­s still in underlying libraries.
 ??  ??
 ??  ?? When you edit with Emacs, you can have the console in one window, the code in another and the applicatio­n window open next to it.
When you edit with Emacs, you can have the console in one window, the code in another and the applicatio­n window open next to it.
 ??  ?? Your default “Hello world” applicatio­n can be run as soon as you have set the files. Whether Proton actually rocks is a matter of opinion.
Your default “Hello world” applicatio­n can be run as soon as you have set the files. Whether Proton actually rocks is a matter of opinion.
 ??  ?? You can use a new terminal and vi to try out other projects. It makes it easier to learn new concepts to try and emulate their efforts.
You can use a new terminal and vi to try out other projects. It makes it easier to learn new concepts to try and emulate their efforts.
 ??  ?? If you have doubts about how things look, start one instance, change the code and then run another instance from a separate terminal.
If you have doubts about how things look, start one instance, change the code and then run another instance from a separate terminal.

Newspapers in English

Newspapers from Australia