Maintenant que nous avons installé notre environnement Windows avec les prérequis, nous allons construire notre première application Desktop avec Elixir-Desktop.
L’idée est de valider le concept de création d’écran réalisé avec Phoenix, écrans qui seront affichés et intégré à l’application Desktop. L’application Windows dispose ainsi d’écran sans faire appel à un navigateur extérieur. Cela reprend le concept proposé par l’outil Electron qui est lui, réalisé en javascript.
Création d’une application phoenix et Elixir hello_desktop
Vérifions les outils installés
Nous allons créer l’application pour l’environnement Windows.
PS C:\Users\berou> elixir -v Erlang/OTP 26 [erts-14.0.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns] Elixir 1.14.5 (compiled with Erlang/OTP 25) PS C:\Users\berou>
Pour mettre à jour Erlang et Elixir nous suivons les étapes définies dans notre article.
C:\Users\broussel>elixir -v Erlang/OTP 26 [erts-14.0.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns] Elixir 1.15.5 (compiled with Erlang/OTP 26) C:\Users\broussel>
Création de l’application mix phx.new
L’application Phoenix est créé sous le nom hello_desktop. Nous souhaitons une application sans base de données. Nous regardons la documentation avec la liste des options pour phx.new :
- mix phx.new hello_desktop
--no-ecto
Sur Windows-10 : mix phx.new hello_desktop –no-ecto
C:\Users\broussel>elixir -v Erlang/OTP 26 [erts-14.0.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns] Elixir 1.15.5 (compiled with Erlang/OTP 26) C:\Users\broussel>cd C:\CarbonX1\Phoenix\Projets C:\CarbonX1\Phoenix\Projets>mix phx.new hello_desktop --no-ecto * creating hello_desktop/config/config.exs * creating hello_desktop/config/dev.exs * creating hello_desktop/config/prod.exs * creating hello_desktop/config/runtime.exs * creating hello_desktop/config/test.exs * creating hello_desktop/lib/hello_desktop/application.ex * creating hello_desktop/lib/hello_desktop.ex * creating hello_desktop/lib/hello_desktop_web/controllers/error_json.ex * creating hello_desktop/lib/hello_desktop_web/endpoint.ex * creating hello_desktop/lib/hello_desktop_web/router.ex * creating hello_desktop/lib/hello_desktop_web/telemetry.ex * creating hello_desktop/lib/hello_desktop_web.ex * creating hello_desktop/mix.exs * creating hello_desktop/README.md * creating hello_desktop/.formatter.exs * creating hello_desktop/.gitignore * creating hello_desktop/test/support/conn_case.ex * creating hello_desktop/test/test_helper.exs * creating hello_desktop/test/hello_desktop_web/controllers/error_json_test.exs * creating hello_desktop/lib/hello_desktop_web/controllers/error_html.ex * creating hello_desktop/test/hello_desktop_web/controllers/error_html_test.exs * creating hello_desktop/lib/hello_desktop_web/components/core_components.ex * creating hello_desktop/lib/hello_desktop_web/controllers/page_controller.ex * creating hello_desktop/lib/hello_desktop_web/controllers/page_html.ex * creating hello_desktop/lib/hello_desktop_web/controllers/page_html/home.html.heex * creating hello_desktop/test/hello_desktop_web/controllers/page_controller_test.exs * creating hello_desktop/lib/hello_desktop_web/components/layouts/root.html.heex * creating hello_desktop/lib/hello_desktop_web/components/layouts/app.html.heex * creating hello_desktop/lib/hello_desktop_web/components/layouts.ex * creating hello_desktop/priv/static/images/logo.svg * creating hello_desktop/lib/hello_desktop/mailer.ex * creating hello_desktop/lib/hello_desktop_web/gettext.ex * creating hello_desktop/priv/gettext/en/LC_MESSAGES/errors.po * creating hello_desktop/priv/gettext/errors.pot * creating hello_desktop/priv/static/robots.txt * creating hello_desktop/priv/static/favicon.ico * creating hello_desktop/assets/js/app.js * creating hello_desktop/assets/vendor/topbar.js * creating hello_desktop/assets/css/app.css * creating hello_desktop/assets/tailwind.config.js * creating hello_desktop/assets/vendor/heroicons/LICENSE.md * creating hello_desktop/assets/vendor/heroicons/UPGRADE.md * extracting hello_desktop/assets/vendor/heroicons/optimized Fetch and install dependencies? [Yn] Y * running mix deps.get * running mix assets.setup * running mix deps.compile We are almost there! The following steps are missing: $ cd hello_desktop Start your Phoenix app with: $ mix phx.server You can also run your app inside IEx (Interactive Elixir) as: $ iex -S mix phx.server C:\CarbonX1\Phoenix\Projets>
Le projet hello_desktop a été créé sur Windows_10. Nous pouvons maintentant réaliser les modifications permettant de transformer le projet en version Desktop. Cela se fait avec VS Code.
Sur Windows_11, nous créons le projet hello :
- dossier : C:\Surface\Phoenix\Projets
- création avec mix : mix phx.new hello
--no-ecto
C:\Users\berou>elixir -v Erlang/OTP 26 [erts-14.0.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns] Elixir 1.15.5 (compiled with Erlang/OTP 26) C:\Users\berou>cd C:\Surface\Phoenix\Projets C:\Surface\Phoenix\Projets>mix phx.new hello --no-ecto * creating hello/config/config.exs * creating hello/config/dev.exs * creating hello/config/prod.exs * creating hello/config/runtime.exs * creating hello/config/test.exs * creating hello/lib/hello/application.ex * creating hello/lib/hello.ex * creating hello/lib/hello_web/controllers/error_json.ex * creating hello/lib/hello_web/endpoint.ex * creating hello/lib/hello_web/router.ex * creating hello/lib/hello_web/telemetry.ex * creating hello/lib/hello_web.ex * creating hello/mix.exs * creating hello/README.md * creating hello/.formatter.exs * creating hello/.gitignore * creating hello/test/support/conn_case.ex * creating hello/test/test_helper.exs * creating hello/test/hello_web/controllers/error_json_test.exs * creating hello/lib/hello_web/controllers/error_html.ex * creating hello/test/hello_web/controllers/error_html_test.exs * creating hello/lib/hello_web/components/core_components.ex * creating hello/lib/hello_web/controllers/page_controller.ex * creating hello/lib/hello_web/controllers/page_html.ex * creating hello/lib/hello_web/controllers/page_html/home.html.heex * creating hello/test/hello_web/controllers/page_controller_test.exs * creating hello/lib/hello_web/components/layouts/root.html.heex * creating hello/lib/hello_web/components/layouts/app.html.heex * creating hello/lib/hello_web/components/layouts.ex * creating hello/priv/static/images/logo.svg * creating hello/lib/hello/mailer.ex * creating hello/lib/hello_web/gettext.ex * creating hello/priv/gettext/en/LC_MESSAGES/errors.po * creating hello/priv/gettext/errors.pot * creating hello/priv/static/robots.txt * creating hello/priv/static/favicon.ico * creating hello/assets/js/app.js * creating hello/assets/vendor/topbar.js * creating hello/assets/css/app.css * creating hello/assets/tailwind.config.js * creating hello/assets/vendor/heroicons/LICENSE.md * creating hello/assets/vendor/heroicons/UPGRADE.md * extracting hello/assets/vendor/heroicons/optimized Fetch and install dependencies? [Yn] Y * running mix deps.get * running mix assets.setup * running mix deps.compile We are almost there! The following steps are missing: $ cd hello Start your Phoenix app with: $ mix phx.server You can also run your app inside IEx (Interactive Elixir) as: $ iex -S mix phx.server C:\Surface\Phoenix\Projets>
Vérification de l’application en mode serveur web
pour lancer le serveur :
- se placer dans le répertoire du projet : cd hello_desktop
- lancer le serveur : mix phx.server
- visualiser le projet dans le navigateur : http://localhost:4000/
Nous pouvons maintenant modifier cette application pour la transformer en mode Desktop.
Adaptation de l’application avec Elixir Desktop
L’application que nous venons de créer est transformée en version Desktop pour Windows.
Le travail à réaliser pour cette transformation est décrit dans la préconisation données par Elixir-Desktop.
Les modifications sont réalisées dans VS Code. Pour ouvrir VS Code :
- Se placer dans le dossier du projet : cd hello_desktop
- Ouvrir VS Code et afficher le projet dans VS Code : code .
Ajout de la dépendance à Desktop
Nous modifions le fichier mix.exs :
mix.exs :
def deps do [ {:desktop, "~> 1.5"} ] end
On réalise l’ajout de desktop en ligne (6). Noter la virgule à la fin de la ligne ajoutée.
mix.exs :
# Specifies your project dependencies. # # Type `mix help deps` for examples and options. defp deps do [ {:desktop, "~> 1.5"}, {:phoenix, "~> 1.7.7"}, {:phoenix_html, "~> 3.3"}, {:phoenix_live_reload, "~> 1.2", only: :dev}, {:phoenix_live_view, "~> 0.19.0"}, {:floki, ">= 0.30.0", only: :test}, {:phoenix_live_dashboard, "~> 0.8.0"}, {:esbuild, "~> 0.7", runtime: Mix.env() == :dev}, {:tailwind, "~> 0.2.0", runtime: Mix.env() == :dev}, {:swoosh, "~> 1.3"}, {:finch, "~> 0.13"}, {:telemetry_metrics, "~> 0.6"}, {:telemetry_poller, "~> 1.0"}, {:gettext, "~> 0.20"}, {:jason, "~> 1.2"}, {:plug_cowboy, "~> 2.5"} ] end
Ajout de la fenêtre desktop dans l’application
On ajoute la fenêtre Dektop qui affichera le contenu de l’application.
application.exs :
children = [{ # After your other children # Starting Desktop.Windows Desktop.Window, [ app: :your_app, id: YourAppWindow, url: &YourAppWeb.Endpoint.url/0 ] }] Supervisor.start_link()
Il convient de remplacer :
- ligne (6), your_app par l’identifiant de l’application. On trouve celui-ci dans mix.exs en ligne (6),
- ligne (7), YourAppWindow par HelloDesktopWindow, YourApp étant HelloDesktop,
- ligne (8), YourAppWeb par HelloDektopWeb,
Dans mix.exs nous avons def project et en ligne (6) : app: suivi du nom de l’application :hello_desktop
mix.exs :
defmodule HelloDesktop.MixProject do use Mix.Project def project do [ app: :hello_desktop, version: "0.1.0", elixir: "~> 1.14", elixirc_paths: elixirc_paths(Mix.env()), start_permanent: Mix.env() == :prod, aliases: aliases(), deps: deps() ] end
lib/hello_desktop/application.ex :
@impl true def start(_type, _args) do children = [ # Start the Telemetry supervisor HelloDesktopWeb.Telemetry, # Start the PubSub system {Phoenix.PubSub, name: HelloDesktop.PubSub}, # Start Finch {Finch, name: HelloDesktop.Finch}, # Start the Endpoint (http/https) HelloDesktopWeb.Endpoint, # Start a worker by calling: HelloDesktop.Worker.start_link(arg) # {HelloDesktop.Worker, arg} # After your other children # Starting Desktop.Windows {Desktop.Window, [ app: :hello_desktop, id: HelloDesktop, url: &HelloDesktopWeb.Endpoint.url/0 ]} ] # See https://hexdocs.pm/elixir/Supervisor.html # for other strategies and supported options opts = [strategy: :one_for_one, name: HelloDesktop.Supervisor] Supervisor.start_link(children, opts) end
Noter l’ajout de la virgule en ligne (11), et les accolades ligne (17) et (22).
Modification du Endpoint pour utiliser Desktop
On remplace Phoenix.Endpoint par Desktop.Endpoint.
endpoint.ex :
defmodule YourAppWeb.Endpoint do use Desktop.Endpoint, otp_app: :your_app
lib/hello_desktop_web/endpoint.ex :
defmodule HelloDesktopWeb.Endpoint do # use Phoenix.Endpoint, otp_app: :hello_desktop use Desktop.Endpoint, otp_app: :hello_desktop
On met en commentaire la ligne initiale
Vérification de la configuration http/port
On change la configuration du serveur pour être en local avec un port à 0.
config.exs :
# Configures the endpoint config :your_app, YourAppWeb.Endpoint, http: [ip: {127, 0, 0, 1}, port: 0], server: true, ...
Nous regardons la configuration du projet exemple sur github
Nous ajoutons ci-dessous les lignes (4) et (11)
config.exs :
# Configures the endpoint config :hello_desktop, HelloDesktopWeb.Endpoint, # url: [host: "localhost"], http: [ip: {127, 0, 0, 1}, port: 0], render_errors: [ formats: [html: HelloDesktopWeb.ErrorHTML, json: HelloDesktopWeb.ErrorJSON], layout: false ], pubsub_server: HelloDesktop.PubSub, live_view: [signing_salt: "oy3Zqaaz"], server: true
Utilisation de la locale du poste qui utilisera l’application
On peut adapter l’application à la locale du poste.
application.ex :
def start(_type, args) do Desktop.identify_default_locale(YourWebApp.Gettext) children = [ ...
On ajoute cette option. YourWebApp est remplacé par HelloDesktopWeb :
application.ex
@impl true def start(_type, _args) do Desktop.identify_default_locale(HelloDesktopWeb.Gettext) children = [ # Start the Telemetry supervisor HelloDesktopWeb.Telemetry, # Start the PubSub system {Phoenix.PubSub, name: HelloDesktop.PubSub}, # Start Finch {Finch, name: HelloDesktop.Finch}, # Start the Endpoint (http/https) HelloDesktopWeb.Endpoint, # Start a worker by calling: HelloDesktop.Worker.start_link(arg) # {HelloDesktop.Worker, arg} # After your other children # Starting Desktop.Windows {Desktop.Window, [ app: :hello_desktop, id: HelloDesktop, title: "HelloDesktop", url: &HelloDesktopWeb.Endpoint.url/0 ]} ]
Noter les lignes 20, 21 et 23. et nous ajoutons title : « HelloDesktop » en ligne 22, qui sera le titre de notre fenêtre.
Compilation et exécution de l’application
nous pouvons maintenant compiler et executer l’application.
C:\CarbonX1\Phoenix\Projets\hello_desktop>mix phx.server Unchecked dependencies for environment dev: * desktop (Hex package) the dependency is not available, run "mix deps.get" ** (Mix) Can't continue due to errors on dependencies C:\CarbonX1\Phoenix\Projets\hello_desktop>
On execute mix deps get :
C:\CarbonX1\Phoenix\Projets\hello_desktop>mix deps.get Resolving Hex dependencies... Resolution completed in 0.316s New: dbus 0.8.0 debouncer 0.1.7 desktop 1.5.2 ex_dbus 0.1.4 ex_sni 0.2.9 oncrash 0.1.0 saxy 1.4.0 Unchanged: castore 1.0.3 cowboy 2.10.0 cowboy_telemetry 0.4.0 cowlib 2.12.1 esbuild 0.7.1 expo 0.4.1 file_system 0.2.10 finch 0.16.0 floki 0.34.3 gettext 0.23.1 hpax 0.1.2 jason 1.4.1 mime 2.0.5 mint 1.5.1 nimble_options 1.0.2 nimble_pool 1.0.0 phoenix 1.7.7 phoenix_html 3.3.2 phoenix_live_dashboard 0.8.1 phoenix_live_reload 1.4.1 phoenix_live_view 0.19.5 phoenix_pubsub 2.1.3 phoenix_template 1.0.3 plug 1.14.2 plug_cowboy 2.6.1 plug_crypto 1.2.5 ranch 1.8.0 swoosh 1.11.5 tailwind 0.2.1 telemetry 1.2.1 telemetry_metrics 0.6.1 telemetry_poller 1.0.0 websock 0.5.3 websock_adapter 0.5.4 * Getting desktop (Hex package) * Getting debouncer (Hex package) * Getting ex_sni (Hex package) * Getting oncrash (Hex package) * Getting ex_dbus (Hex package) * Getting saxy (Hex package) * Getting dbus (Hex package) C:\CarbonX1\Phoenix\Projets\hello_desktop>
Nous executons l’application :
- cd hello_desktop
- mix phx.server
l’application s’ouvre lentement.
C:\CarbonX1\Phoenix\Projets\hello_desktop>mix phx.server Compiling 1 file (.ex) [warning] Phoenix is unable to create symlinks. Phoenix' code reloader will run considerably faster if symlinks are allowed. On Windows, the lack of symlinks may even cause empty assets to be served. Luckily, you can address this issue by starting your Windows terminal at least once with "Run as Administrator" and then running your Phoenix application. [info] Running HelloDesktopWeb.Endpoint with cowboy 2.10.0 at 127.0.0.1:4000 (http) [info] Access HelloDesktopWeb.Endpoint at http://localhost:4000 [watch] build finished, watching for changes... [info] Showing http://localhost:4000?k=ATRMWXWNAQ4KYSGTA3Q5BX2UURXL4BK2DQIF32P2I2DXQM6NKTAA [info] Rebuilding WebView on Windows with url: "http://localhost:4000?k=ATRMWXWNAQ4KYSGTA3Q5BX2UURXL4BK2DQIF32P2I2DXQM6NKTAA" Rebuilding... Done in 874ms. [info] GET / [debug] Processing with HelloDesktopWeb.PageController.home/2 Parameters: %{"k" => "ATRMWXWNAQ4KYSGTA3Q5BX2UURXL4BK2DQIF32P2I2DXQM6NKTAA"} Pipelines: [:browser] [info] Sent 200 in 927ms [info] Showing http://localhost:4000?k=ATRMWXWNAQ4KYSGTA3Q5BX2UURXL4BK2DQIF32P2I2DXQM6NKTAA [info] GET / [debug] Processing with HelloDesktopWeb.PageController.home/2 Parameters: %{"k" => "ATRMWXWNAQ4KYSGTA3Q5BX2UURXL4BK2DQIF32P2I2DXQM6NKTAA"} Pipelines: [:browser] [info] Sent 200 in 614µs [info] Rebuilding WebView on Windows with url: "http://localhost:4000?k=ATRMWXWNAQ4KYSGTA3Q5BX2UURXL4BK2DQIF32P2I2DXQM6NKTAA" [info] GET / [debug] Processing with HelloDesktopWeb.PageController.home/2 Parameters: %{"k" => "ATRMWXWNAQ4KYSGTA3Q5BX2UURXL4BK2DQIF32P2I2DXQM6NKTAA"} Pipelines: [:browser] [info] Sent 200 in 512µs [info] Showing http://localhost:4000?k=ATRMWXWNAQ4KYSGTA3Q5BX2UURXL4BK2DQIF32P2I2DXQM6NKTAA [info] GET / [debug] Processing with HelloDesktopWeb.PageController.home/2 Parameters: %{"k" => "ATRMWXWNAQ4KYSGTA3Q5BX2UURXL4BK2DQIF32P2I2DXQM6NKTAA"} Pipelines: [:browser] [info] Sent 200 in 819µs [info] Rebuilding WebView on Windows with url: "http://localhost:4000?k=ATRMWXWNAQ4KYSGTA3Q5BX2UURXL4BK2DQIF32P2I2DXQM6NKTAA" [info] Showing http://localhost:4000?k=ATRMWXWNAQ4KYSGTA3Q5BX2UURXL4BK2DQIF32P2I2DXQM6NKTAA [info] GET / [debug] Processing with HelloDesktopWeb.PageController.home/2 Parameters: %{"k" => "ATRMWXWNAQ4KYSGTA3Q5BX2UURXL4BK2DQIF32P2I2DXQM6NKTAA"} Pipelines: [:browser] [info] Sent 200 in 716µs [info] GET / [debug] Processing with HelloDesktopWeb.PageController.home/2 Parameters: %{"k" => "ATRMWXWNAQ4KYSGTA3Q5BX2UURXL4BK2DQIF32P2I2DXQM6NKTAA"} Pipelines: [:browser] [info] Sent 200 in 614µs [info] Rebuilding WebView on Windows with url: "http://localhost:4000?k=ATRMWXWNAQ4KYSGTA3Q5BX2UURXL4BK2DQIF32P2I2DXQM6NKTAA" [info] Showing http://localhost:4000?k=ATRMWXWNAQ4KYSGTA3Q5BX2UURXL4BK2DQIF32P2I2DXQM6NKTAA [info] GET / [debug] Processing with HelloDesktopWeb.PageController.home/2 Parameters: %{"k" => "ATRMWXWNAQ4KYSGTA3Q5BX2UURXL4BK2DQIF32P2I2DXQM6NKTAA"} Pipelines: [:browser] [info] Sent 200 in 819µs [info] GET / [debug] Processing with HelloDesktopWeb.PageController.home/2 Parameters: %{"k" => "ATRMWXWNAQ4KYSGTA3Q5BX2UURXL4BK2DQIF32P2I2DXQM6NKTAA"} Pipelines: [:browser] [info] Sent 200 in 921µs [info] Rebuilding WebView on Windows with url: "http://localhost:4000?k=ATRMWXWNAQ4KYSGTA3Q5BX2UURXL4BK2DQIF32P2I2DXQM6NKTAA" [info] GET / [debug] Processing with HelloDesktopWeb.PageController.home/2 Parameters: %{"k" => "ATRMWXWNAQ4KYSGTA3Q5BX2UURXL4BK2DQIF32P2I2DXQM6NKTAA"} Pipelines: [:browser] [info] Sent 200 in 819µs [info] Shutting down 5 sockets in 1 rounds of 2000ms [notice] Application hello_desktop exited: shutdown
L’application ouvre la page Phoenix :
La fenêtre s’ouvre directement, sans avoir besoin de passer par un navigateur.
Nous avons eu l’impression qu’il était difficile de fermer l’application avec la croix en haut à droite. Nous devons refaire un essai.
Ajout des fichiers statiques
Nous pouvons ajouter les fichiers images dans l’application, en particulier les icônes de l’application.
Distribution de l’application
Pour distribuer l’application, nous devons créer un exécutable.
Conclusion
Nous avons réussi à créer l’application minimale HelloDesktop. L’application se lance avec mix phx.server
Nous devons encore :
- regarder comment se distribue l’application.
- voir la création d’une application avec base de données intégrées.
- créer la même application sur Mac, Android et ios
Cela fera l’objet de nouveaux articles.