Dart: sviluppare una Chrome Packaged App

Di - 2 February 2013 - in

Durante il corso di questa rubrica ci siamo soffermati spesso sulle caratteristiche di Dart Editor, evidenziandone quelle che, oltre a semplificare la fase di stesura del codice, consentono all’utente di imparare ad usare Dart al meglio. Dalla build 0.3.1.1_r17328, rilasciata il 22 Gennaio 2013, è stato integrato nell’Editor un wizard per la creazione di Chrome Packaged Apps; questo tipo di applicazioni sono particolarmente interessanti perché consentono di sviluppare robuste applicazioni web con l’ausilio delle chrome.* APIs, che ne estendono notevolmente il campo di azione.

Nell’articolo di oggi vedremo come creare una semplicissima Chrome Packaged App che esegue una ricerca su Twitter e mostra i risultati.

Per iniziare abbiamo bisogno di:

  • Una versione di Google Chrome uguale o superiore a 23
  • L’ultima versione di Dart Editor
  • Il codice sorgente dell’applicazione cercaSuTwitter

Apriamo il Dart Editor e assicuriamoci di avere l’ultima versione disponibile, Tools -> Preferences -> Update

Screenshot

Scegliamo di creare una nuova applicazione, File -> New Application e nella scheda Sample content selezioniamo Chrome packaged application.

Screenshot

A questo punto la directory della nostra applicazione avrà questa forma:

├── build.dart
├── packages
│   ├── browser -> /home/utente/.pub-cache/hosted/pub.dartlang.org/browser-0.3.2/lib
│   ├── js -> /home/utente/.pub-cache/hosted/pub.dartlang.org/js-0.0.15/lib
│   ├── meta -> /home/utente/.pub-cache/hosted/pub.dartlang.org/meta-0.3.2/lib
│   └── unittest -> /home/utente/.pub-cache/hosted/pub.dartlang.org/unittest-0.3.2/lib
├── pubspec.lock
├── pubspec.yaml
├── README.md
└── web
    ├── cercasutwitter.css
    ├── cercasutwitter.dart
    ├── cercasutwitter.dart.js
    ├── cercasutwitter.dart.js.deps
    ├── cercasutwitter.dart.js.map
    ├── cercasutwitter.html
    ├── dart_icon.png
    ├── main.js
    ├── manifest.json
    └── packages -> /home/utente/dart/cercaSuTwitter/packages

Diamo uno sguardo alle componenti fondamentali della nostra Chrome Packaged App:

  • manifest.json

    Nel manifest sono dichiarate le proprietà dell’applicazione: versione del manifest, nome dell’applicazione, versione dell’applicazione, icone, permessi e risorse dell’app. Nel nostro caso le risorse dell’app sono:

      "app": {
        "background": {
            "scripts": ["main.js"]
        }

    La nostra app dovrà interagire con Twitter per reperire i dati, quindi dobbiamo dichiarare che l’app abbia permessi sufficienti aggiungendo questa riga al manifest:

     "permissions": ["https://search.twitter.com/*"]

    Il file manifest.json si presenterà dunque così:

    {
      "manifest_version": 2,
      "name": "cercaSuTwitter",
      "version": "1",
      "minimum_chrome_version": "23",
      "icons": {"128": "dart_icon.png"},
      "app": {
        "background": {
          "scripts": ["main.js"]
        }
      },
      "permissions": ["https://search.twitter.com/*"]
    }
  • main.js

    Questo è lo script che viene eseguito all’avvio dell’applicazione:

    chrome.app.runtime.onLaunched.addListener(function() {
      chrome.app.window.create('cercasutwitter.html',
        {id: 'cercasutwitter', width: 800, height: 600});
    });

    Lo scopo dello script è creare una finestra di dimensioni 800×600 e caricare il file cercasutwitter.html

  • cercasutwitter.html

    È l’interfaccia HTML.

    <input id="cerca" type="text"/>
    <button id="btn">Cerca su Twitter</button>
    <div id="boxRisultati"></div>
    
    <script src="packages/browser/dart.js"></script>
    <script src="packages/js/dart_interop.js"></script>
    <script src="packagd.dart.js"></script>

Vediamo ora nello specifico il codice DART del file cercasutwitter.dart. Innanzitutto vediamo quali sono le librerie necessarie:

import 'dart:html';
import 'dart:json' as JSON;
import 'package:js/js.dart' as js;

Passiamo ora alla panoramica sulle funzioni principali dell’applicazione:

  • main()

    Richiesto, è l’entry point dell’applicazione. Abbina determinati elementi del DOM a funzioni in DART e chiama la funzione cerca("engeene");

  • cerca(String q)

    Se il valore in input non è vuoto, effettua una richiesta HTTP (cfr. XMLHttpRequest) all’url https://search.twitter.com/search.json?q=${q}&rpp=10";, dove i parametri q e rpp indicano rispettivamente la query e il numero di risultati da mostrare per pagina.

    Il metodo HttpRequest.get() accetta due parametri, String url e onComplete(HttpRequest request); quest’ultima funzione è la callback da invocare quando la richiesta riceve un responso dal server. Nel nostro caso la funzione di callback è mostra(HttpRequest req).

  • mostra(HttpRequest req)

    Ha il compito di mostrare i risultati. Sorvoliamo le funzioni per la manipolazione del DOM, già viste durante il corso della rubrica, e soffermiamoci sulla funzione JSON.parse() definita nella libreria dart:json. Intuitivamente, questa funzione agevola la gestione del messaggio JSON (JavaScript Notation Object) ricevuto dal server.

    L’istruzione

    Map tweets = JSON.parse(req.response)["results"];

    ci consente infatti di trattare il responso del server come un oggetto Map, includendo nella mappa solo il campo results (è disponibile su gist.github.com un esempio di messaggio completo ricevuto da search.twitter.com).

    Il valore del testo del n-esimo tweet sarà tweets[n]["text"], l’autore sarà tweets[n]["from_user"], la data sarà tweets[n]["created_at"] e così via.

In aggiunta a queste funzioni, distanzaNelTempo(String twitterTimestamp), meseDaStringa() e desinenza() ci permettono di ottenere valori user-friendly:

  • distanzaNelTempo(String twitterTimestamp)

    Prende in ingresso il timestamp del tweet nella forma “Fri, 01 Feb 2013 10:44:19 +0000” e restituisce una stringa nella forma “20 ore fa“, “circa 1 mese fa“, etc. Per ottenere questo risultato, l’applicazione analizza la stringa e la converte in un oggetto DateTime che poi viene sottratto da un altro oggetto DateTime che rappresenta l’orario corrente.

    DateTime dataCorrente = new DateTime.now();
    DateTime dataTweet = new DateTime(anno,mese,giorno,ora,minuto,secondo).add(dataCorrente.timeZoneOffset);
    . . .
    int tempoTrascorso = dataCorrente.difference(dataTweet).inMilliseconds;

A questo punto siamo pronti per caricare l’applicazione in Google Chrome:

  • compiliamo il file cercasutwitter.dart in Javascript dal Dart Editor, Tools -> Generate Javascript (CTRL + SHIFT + G)
  • apriamo il pannello delle estensioni all’URL chrome://extensions
  • abilitiamo la Modalità sviluppatore, facciamo clic su “Carica estensione non pacchettizzata…” e scegliamo di caricare la directory cercaSuTwitter/web

    Screenshot

  • avviamo l’applicazione, accessibile dalla home di Google Chrome

Screenshot

Come sempre, il codice di questa applicazione è disponibile sull’account Engeene su GitHub. Nel prossimo articolo parleremo degli ultimi aggiornamenti al Dart SDK, ormai sempre più vicino al raggiungimento del Milestone 3.

Leave a Reply

Claudio d'Angelis Articolo scritto da

Programmatore e studente di Informatica, appassionato di musica, web e sistemi UNIX. Collabora con Googlab dall'Ottobre 2012.

Contatta l'autore

Previous post:

Next post: