<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Flutter and Other Experiments]]></title><description><![CDATA[I love programming and I work as a Software Engineer on Web and Mobile Apps. I'm expanding my knowledge on Flutter and Dart I post content about these two technologies]]></description><link>https://blog.albertobonacina.com</link><generator>RSS for Node</generator><lastBuildDate>Sun, 12 Apr 2026 23:12:40 GMT</lastBuildDate><atom:link href="https://blog.albertobonacina.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Boosting Productivity: A Guide to Building a Reading List App with Notion and Flutter Web]]></title><description><![CDATA[This post will demonstrate how to use Flutter Web to create a dashboard displaying our reading list. The dashboard will show the books we are reading, those we have already read, and the ones we plan to read.
For the development of our application, w...]]></description><link>https://blog.albertobonacina.com/boosting-productivity-a-guide-to-building-a-reading-list-app-with-notion-and-flutter-web</link><guid isPermaLink="true">https://blog.albertobonacina.com/boosting-productivity-a-guide-to-building-a-reading-list-app-with-notion-and-flutter-web</guid><category><![CDATA[Flutter]]></category><category><![CDATA[notion]]></category><category><![CDATA[dashboard]]></category><category><![CDATA[cloudflare]]></category><category><![CDATA[Netlify]]></category><dc:creator><![CDATA[Alberto Bonacina]]></dc:creator><pubDate>Sat, 29 Jul 2023 10:36:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1690319672939/deec477e-0b49-479a-b6ec-e1b32defbcec.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This post will demonstrate how to use Flutter Web to create a dashboard displaying our reading list. The dashboard will show the books we are reading, those we have already read, and the ones we plan to read.</p>
<p>For the development of our application, we will use <a target="_blank" href="https://flutter.dev/">Flutter</a> to create our Web-based dashboard and a <a target="_blank" href="https://www.notion.so/">Notion</a> database to manage persistence and save the list of our books. The final result can be found here: <a target="_blank" href="https://myreadings.albertobonacina.com/">My Reading List</a></p>
<p>The code for the application is available in this repo on GitHub: <a target="_blank" href="https://github.com/polilluminato/myreadings-flutter">myreadings-flutter</a> licensed <a target="_blank" href="https://github.com/polilluminato/myreadings-flutter/blob/main/LICENSE.md">Apache 2.0</a>.</p>
<h2 id="heading-notion-database">Notion Database</h2>
<p>A <a target="_blank" href="https://www.notion.so/help/category/databases">Notion database</a> is nothing more than a table that can have columns characterizing the data and can be sorted according to different sorting criteria. For this project, the columns that have been created have this meaning:</p>
<ul>
<li><p>Finished: indicates whether or not the book has been completed</p>
</li>
<li><p>Cover: link to the image of the book cover taken from Amazon</p>
</li>
<li><p>Title: title of the book, in my case in Italian</p>
</li>
<li><p>Author: author(s) of the book. In this case, the value is put directly into the cell and there is no relation to external master tables</p>
</li>
<li><p>Date: the date on which the book was finished and which is used later for sorting</p>
</li>
<li><p>Progress: number representing the percentage progress of pages read compared to total pages read</p>
</li>
<li><p>Link: sponsored link to Amazon</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690404326857/8fba546e-b24d-406c-92da-747b2e7b9511.png" alt class="image--center mx-auto" /></p>
<p>In order to access our Notion database from the outside via the API provided we must first create an <a target="_blank" href="https://developers.notion.com/docs/create-a-notion-integration">Integration</a> to which we must give read privileges to our database. Once the application is created we will be given a secret in the form <code>secret_XXX</code> which we must use to authenticate ourselves in our calls to the Notion API. Following the <a target="_blank" href="https://developers.notion.com/docs/working-with-databases">documentation</a>, to access a Notion database via the API the call to make is this:</p>
<pre><code class="lang-bash">curl --location <span class="hljs-string">'https://api.notion.com/v1/databases/${NOTION_DB}/query'</span> \
--header <span class="hljs-string">'Authorization: Bearer ${NOTION_SECRET}'</span> \
--header <span class="hljs-string">'Content-Type: application/json'</span> \
--header <span class="hljs-string">'Notion-Version: 2022-06-28'</span> \
--data <span class="hljs-string">'{
    "page_size": 100,
    "sorts": [
        ...
    ]
}'</span>
</code></pre>
<p>Where two variables are present:</p>
<ul>
<li><p><em>NOTION_DB</em>: which can be found in the URL of the page that corresponds to the database</p>
</li>
<li><p><em>NOTION_SECRET</em>: is returned to us when we have created the integration to use the API</p>
</li>
</ul>
<p>In my case, I also set up a particular sorting in which the <code>sorts</code> array where the call, as stated in the documentation for <a target="_blank" href="https://developers.notion.com/reference/post-database-query-sort">Sort database entries</a>, is made like this:</p>
<pre><code class="lang-json"><span class="hljs-string">"sorts"</span>: [
  {
    <span class="hljs-attr">"property"</span>: <span class="hljs-string">"Finished"</span>,
    <span class="hljs-attr">"direction"</span>: <span class="hljs-string">"ascending"</span>
  },
  {
    <span class="hljs-attr">"property"</span>: <span class="hljs-string">"Progress"</span>,
    <span class="hljs-attr">"direction"</span>: <span class="hljs-string">"descending"</span>
  },
  {
    <span class="hljs-attr">"property"</span>: <span class="hljs-string">"Date"</span>,
    <span class="hljs-attr">"direction"</span>: <span class="hljs-string">"descending"</span>
  }
]
</code></pre>
<p>Because I want the books I haven't finished yet to be there first and then the ones that are completed, the ones that are being read to be sorted by the progress field, and finally the ones that have been read I want to have sorted from the one I finished most recently to the one I read first.</p>
<p>This way I can modify the Notion database as I want, adding books, editing information, and automatically the results will be displayed within the dashboard.</p>
<h2 id="heading-flutter-web-app">Flutter Web App</h2>
<p>The Flutter application is very simple because it only cares to make a call to the Notion API via the <a target="_blank" href="https://pub.dev/packages/http">http</a> package and displays the results in a grid, with the help of the very useful <a target="_blank" href="https://pub.dev/packages/flutter_staggered_grid_view">flutter_staggered_grid_view</a> package (about which I have already done an article <a target="_blank" href="https://blog.albertobonacina.com/create-a-simple-responsive-gridview-with-flutter">here</a>). Other packages that were used in the project are:</p>
<ul>
<li><p><a target="_blank" href="https://pub.dev/packages/riverpod">riverpod</a> to manage the application state and HTTP call via a provider and its repository</p>
</li>
<li><p><a target="_blank" href="https://pub.dev/packages/go_router">go_router</a> for navigation and routing</p>
</li>
<li><p><a target="_blank" href="https://pub.dev/packages/percent_indicator">percent_indicator</a> for the loading bar indicating progress in reading</p>
</li>
<li><p><a target="_blank" href="https://pub.dev/packages/super_banners">super_banners</a> for the banner above the card for the status of planned and read</p>
</li>
<li><p><a target="_blank" href="https://pub.dev/packages/url_launcher">url_launcher</a> for opening the link to the Amazon page upon clicking the button</p>
</li>
</ul>
<p>The end result is as shown in the figure:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690406268783/1986ab65-86ab-45b9-8769-2bb951b8d68c.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-insights">Insights</h2>
<p>As reported in these two discussions on StackOverflow: <a target="_blank" href="https://stackoverflow.com/questions/68781041/notion-api-vanilla-js-fetch-does-not-work">Notion API, Vanilla JS, Fetch does not work [duplicate]</a> and <a target="_blank" href="https://stackoverflow.com/questions/68015381/can-i-use-fetch-to-call-the-notion-api">Can I use fetch to call the Notion API?</a>, it is not possible to call the Notion API directly from a web page due to a problem with <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS">CORS</a>; to solve this problem, a <a target="_blank" href="https://workers.cloudflare.com/">Cloudflare Worker</a> was used that acts as middleware between the web page and the Notion API allowing for a result that then returns to the web page.</p>
<p>To improve the development experience, a much-simplified version of CI/CD has been implemented that allows each push on the main branch of the repository to automatically start a build on <a target="_blank" href="https://www.netlify.com/">Netlify</a> that deploy the web app directly to <a target="_blank" href="http://myreadings.albertobonacina.com">myreadings.albertobonacina.com</a></p>
<p>The architecture is in the figure and more details on configurations on environment variables, code for deployment, and release can be found directly in the repository on GitHub:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690625365564/4e8c1838-e52c-48c3-b996-6a79e9780d72.jpeg" alt class="image--center mx-auto" /></p>
<h3 id="heading-conclusions">Conclusions</h3>
<p>The final result can be viewed on this webpage: <a target="_blank" href="https://myreadings.albertobonacina.com">myreadings.albertobonacina.com</a> and all the code can be found in this repo on GitHub: <a target="_blank" href="https://github.com/polilluminato/myreadings-flutter">myreadings-flutter</a></p>
<p>Code strong, Alberto</p>
]]></content:encoded></item><item><title><![CDATA[Theme and Accent Color switch with Riverpod in Flutter]]></title><description><![CDATA[This article explores the seamless integration of Riverpod's state management capabilities with Flutter's theming system, enabling you to create dynamic and customizable UIs, you will learn how to define and update themes and leverage Riverpod's prov...]]></description><link>https://blog.albertobonacina.com/theme-and-accent-color-switch-with-riverpod-in-flutter</link><guid isPermaLink="true">https://blog.albertobonacina.com/theme-and-accent-color-switch-with-riverpod-in-flutter</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Flutter Examples]]></category><category><![CDATA[theme]]></category><category><![CDATA[dark mode]]></category><category><![CDATA[Riverpod]]></category><dc:creator><![CDATA[Alberto Bonacina]]></dc:creator><pubDate>Fri, 14 Jul 2023 13:38:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1689335413656/30fb8bd2-22d3-495c-a987-51364c12182d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This article explores the seamless integration of Riverpod's state management capabilities with Flutter's theming system, enabling you to create dynamic and customizable UIs, you will learn how to define and update themes and leverage Riverpod's providers to manage accent color with ease.</p>
<p>There are several techniques to manage users' preferences and allow them to choose dark or light themes, which can be considered a feature that all applications should have, and accent color to change the application's theme. This last feature is not so common because often colors inside the application are imposed by the brand or recently they are increasingly using the system theme as described by the <a target="_blank" href="https://material.io/blog/start-building-with-material-you">Material You</a> guidelines on Android and which is mainly based on this aspect:</p>
<blockquote>
<p>custom palettes that emphasize expression and accessibility are algorithmically generated based on your brand or—starting with Pixel—an individual’s wallpaper</p>
</blockquote>
<p>However, wanting to give default choices to the user we will see in this article how to set up an application so that it is easy for the user to change preferences and see in real time how the theme of the application changes.</p>
<p>The final application is this and allows you to choose whether to use the dark or light theme and set the accent color with which all the colors related to the theme will be created:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1689109849304/9fed9687-6dea-49da-a7fb-b29cab420afe.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-main-aspects-and-implementation">Main aspects and implementation</h2>
<p>The only essential dependency that we will need in this project will be <a target="_blank" href="https://riverpod.dev/">Riverpod</a> which will handle the application state and the theme and accent color information so in our <code>pubspec.yaml</code> we are going to add the <a target="_blank" href="https://pub.dev/packages/flutter_riverpod">flutter_riverpod</a> dependency:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">dependencies:</span>
  <span class="hljs-string">...</span>
  <span class="hljs-attr">flutter_riverpod:</span> <span class="hljs-string">^2.3.6</span>
</code></pre>
<p>At this point, we wrap the whole application in the <strong>ProviderScope</strong> to make <strong>Riverpod</strong> manage the application state:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">void</span> main() <span class="hljs-keyword">async</span> {
  WidgetsFlutterBinding.ensureInitialized();

  runApp(
    ProviderScope(
      child: App(),
    ),
  );
}
</code></pre>
<p>To read and update the status of the theme and accent color, the most important part of <strong>Riverpod</strong> is used: <a target="_blank" href="https://riverpod.dev/docs/concepts/providers">providers</a>. Providers are objects that contain within them a state and allow this state to be read and modified. In particular, in this application it was sufficient to use a <a target="_blank" href="https://riverpod.dev/docs/providers/state_provider">StateProvider</a> since the information that needs to be managed is "simple": <em>Brightness</em> and <em>Color</em>. So I create a <code>theme_provider.dart</code> that will contain two providers that will manage the dark and light theme and accent color of the application:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">final</span> isDarkModeProvider = StateProvider&lt;Brightness&gt;((ref) 
                               =&gt; Brightness.light);

<span class="hljs-keyword">final</span> accentColorProvider = StateProvider&lt;Color&gt;((ref) 
                               =&gt; Colors.indigo);
</code></pre>
<p>To manage the change of accent color, the custom widget was created <code>AccentColorButton</code> whose basic parts are:</p>
<pre><code class="lang-dart">Widget build(BuildContext context, WidgetRef ref) {
    <span class="hljs-comment">//reference to the accent color provider</span>
    <span class="hljs-keyword">final</span> acProvider = ref.watch(accentColorProvider);
    <span class="hljs-built_in">double</span> size = <span class="hljs-number">32</span>;

    <span class="hljs-keyword">return</span> InkWell(
      <span class="hljs-comment">//On tap I update the provider value by changing its status </span>
      <span class="hljs-comment">//to the new color selected</span>
      onTap: () =&gt; ref.read(accentColorProvider.notifier).update((state) =&gt; color),
      child: Container(
        decoration: BoxDecoration(
          border: Border.all(
            ...
            <span class="hljs-comment">//I update the color of the button's border </span>
            <span class="hljs-comment">//by making it color if that button has been clicked</span>
            color: acProvider == color ? color : Colors.transparent,
          ),
          ...
        ),
        ...
      ),
    );
  }
</code></pre>
<p>An entirely similar argument can be made for the <code>ThemeButton</code> widget that takes care of reading and updating the status of the <code>brightnessProvider</code>.</p>
<p>To update the entire style of the application, it is then sufficient to add in the <code>MaterialApp</code> the reference to the two providers:</p>
<pre><code class="lang-dart">Widget build(BuildContext context, WidgetRef ref) {
  <span class="hljs-keyword">return</span> MaterialApp.router(
    ...
    theme: ThemeData(
      ...
      colorScheme: ColorScheme.fromSeed(
        seedColor: ref.watch(accentColorProvider),
        brightness: ref.watch(brightnessProvider),
      )
    ),
  );
}
</code></pre>
<h3 id="heading-conclusions">Conclusions</h3>
<p>These customizations are usually added in the settings section of the app to allow the user to customize their user experience, but in this article, we have placed them directly on the home page to give them more importance.</p>
<p>In this GitHub repository, you can find the source code of the application developed for this article: <a target="_blank" href="https://github.com/polilluminato/theme-accent-color-switch-flutter">theme-accent-color-switch-flutter</a>.</p>
<p>Code strong, Alberto</p>
]]></content:encoded></item><item><title><![CDATA[How to properly organize your API EndPoints in Flutter]]></title><description><![CDATA[Hi everyone, in this post, I'll show you how I organize my API call in one class to manage my API endpoint better and pass parameters to them.
If you've got an app that syncs or gets information from a third-party service you must call some API from ...]]></description><link>https://blog.albertobonacina.com/how-to-properly-organize-your-api-endpoints-in-flutter</link><guid isPermaLink="true">https://blog.albertobonacina.com/how-to-properly-organize-your-api-endpoints-in-flutter</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Flutter Examples]]></category><category><![CDATA[APIs]]></category><category><![CDATA[API basics ]]></category><category><![CDATA[http]]></category><dc:creator><![CDATA[Alberto Bonacina]]></dc:creator><pubDate>Fri, 20 Jan 2023 13:47:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1674200275215/f4d69b9a-5342-4625-8ad4-5f8db2bf8bdf.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hi everyone, in this post, I'll show you how I organize my API call in one class to manage my API endpoint better and pass parameters to them.</p>
<p>If you've got an app that syncs or gets information from a third-party service you must call some API from your code and it is often tempting to write endpoints directly within our HTTP calls, more or less like this:</p>
<pre><code class="lang-dart"><span class="hljs-comment">//Worst case</span>
Future&lt;MyClass&gt; callEndPoint(<span class="hljs-built_in">int</span> id) <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">var</span> response = <span class="hljs-keyword">await</span> http.<span class="hljs-keyword">get</span>(<span class="hljs-built_in">Uri</span>.parse(<span class="hljs-string">"https://myendpointurl/myclass/<span class="hljs-subst">$id</span>"</span>));
    ...
}

<span class="hljs-comment">//not that much worse</span>
Future&lt;MyClass&gt; callEndPoint(<span class="hljs-built_in">int</span> id) <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">var</span> response = <span class="hljs-keyword">await</span>     http.<span class="hljs-keyword">get</span>(<span class="hljs-built_in">Uri</span>.parse(<span class="hljs-string">"<span class="hljs-subst">${Env.BASE_URL}</span>/myclass/<span class="hljs-subst">$id</span>"</span>));
    ...
}
</code></pre>
<p>but it is not good practice to hardcode endpoints in all calls, and it is a tad better to manage an environment variable or constant that defines our <code>BASE_URL</code> for calls.</p>
<h2 id="heading-my-solution">My solution</h2>
<p>The solution I have adopted for some time in all my projects is to create an ApiEndPoint class where I define all my endpoints and the parameters I need to manage. So for example to implement calls to the <a target="_blank" href="https://swapi.dev/">Star Wars API</a> I can do it this way:</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ApiEndPoint</span> </span>{

  <span class="hljs-keyword">late</span> <span class="hljs-built_in">String</span> FILM_ALL;
  <span class="hljs-keyword">late</span> <span class="hljs-built_in">String</span> FILM_SINGLE;

  ApiEndPoint({<span class="hljs-built_in">int?</span> id}) {

    <span class="hljs-comment">//Value added for simplicity but it is always better </span>
    <span class="hljs-comment">//  to add it in a configuration file</span>
    <span class="hljs-built_in">String</span> baseUrlPath = <span class="hljs-string">'https://swapi.dev/api'</span>;

    FILM_ALL = <span class="hljs-string">'<span class="hljs-subst">$baseUrlPath</span>/films/'</span>;
    FILM_SINGLE = <span class="hljs-string">'<span class="hljs-subst">$baseUrlPath</span>/films/<span class="hljs-subst">$id</span>'</span>;
  }
}
</code></pre>
<p>That way when I need to call the endpoint to get the list of movies I just type in:</p>
<pre><code class="lang-dart">Future&lt;<span class="hljs-built_in">List</span>&lt;Film&gt;&gt; getAllFilms() <span class="hljs-keyword">async</span> {
  <span class="hljs-keyword">var</span> response = <span class="hljs-keyword">await</span> http.<span class="hljs-keyword">get</span>(
    <span class="hljs-built_in">Uri</span>.parse(ApiEndPoint().FILM_ALL),
  );
  <span class="hljs-comment">//...</span>
}
</code></pre>
<p>And if this endpoint requires input parameters, such as the endpoint to get the information about a single movie, simply write:</p>
<pre><code class="lang-dart">Future&lt;Film&gt; getSingleFilm(<span class="hljs-built_in">int</span> idFilm) <span class="hljs-keyword">async</span> {
  <span class="hljs-keyword">var</span> response = <span class="hljs-keyword">await</span> http.<span class="hljs-keyword">get</span>(
    <span class="hljs-built_in">Uri</span>.parse(ApiEndPoint(id: idFilm).FILM_SINGLE),
  );
  <span class="hljs-comment">//...</span>
}
</code></pre>
<p>Easy isn't it?</p>
<p>I find this setup useful and with the following advantages:</p>
<ul>
<li><p>I have a single class with the responsibility of managing my EndPoints and organizing the paths as required by the API;</p>
</li>
<li><p>I can easily pass input parameters without worrying about URL formatting;</p>
</li>
<li><p>In my repositories and in my HTTP calls I can tell right away what API it is without going to the URL to figure it out because I have made it explicit in the attributes of my ApiEndPoint class;</p>
</li>
<li><p>In the most extreme case, I can switch to another API without having to change my HTTP calls but only by changing the URLs within the ApiEndPoint class;</p>
</li>
</ul>
<p>Code strong, Alberto</p>
<p>Cover Photo by <a target="_blank" href="https://www.pexels.com/it-it/@orlovamaria/">Maria Orlova</a>: <a target="_blank" href="https://www.pexels.com/it-it/foto/angolo-della-casa-invecchiata-vicino-al-posto-di-direzione-in-citta-4915846/">Corner Of Aged House Near Direction Post In Town</a></p>
]]></content:encoded></item><item><title><![CDATA[ENVied: the best way to handle your environment variables in Flutter]]></title><description><![CDATA[Hi everyone, in this post, I want to show you the best way to store environment variables in a Flutter project that I started to use some months ago in all of my projects after seeing it in this blog post from CodewithAndrea: How to Store API Keys in...]]></description><link>https://blog.albertobonacina.com/envied-the-best-way-to-handle-your-environment-variables-in-flutter</link><guid isPermaLink="true">https://blog.albertobonacina.com/envied-the-best-way-to-handle-your-environment-variables-in-flutter</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Dart]]></category><category><![CDATA[Flutter Examples]]></category><category><![CDATA[app development]]></category><dc:creator><![CDATA[Alberto Bonacina]]></dc:creator><pubDate>Fri, 13 Jan 2023 16:53:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1673628641920/579cf6c6-205d-43d3-847c-aec2844be4db.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hi everyone, in this post, I want to show you the best way to store environment variables in a Flutter project that I started to use some months ago in all of my projects after seeing it in this blog post from CodewithAndrea: <a target="_blank" href="https://codewithandrea.com/articles/flutter-api-keys-dart-define-env-files/">How to Store API Keys in Flutter: --dart-define vs .env files</a>.</p>
<p>In an application that communicates with external services, that needs to authenticate via API key or to configure particular settings we must set environment variables that must be kept as hidden as possible, especially those related to API keys, but rather conveniently to be used in our Flutter applications.</p>
<p>For all this, we are helped by the valid <a target="_blank" href="https://pub.dev/packages/envied">ENVied</a> package that lets you create a convenient Dart class that maps the <code>.env</code> file. To install it we can add it to the <code>pubspec.yaml</code> file along with <code>envied_generator</code> and <code>build_runner</code> for the build step and generation of the Dart class:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">dependencies:</span>
  <span class="hljs-string">...</span>
  <span class="hljs-attr">envied:</span> <span class="hljs-string">^0.3.0</span>

<span class="hljs-attr">dev_dependencies:</span>
  <span class="hljs-string">...</span>
  <span class="hljs-attr">envied_generator:</span> <span class="hljs-string">^0.3.0</span>
  <span class="hljs-attr">build_runner:</span> <span class="hljs-string">^2.3.3</span>
</code></pre>
<p>Now we can create an <code>.env</code> file inside our project where we can add all our environment variables like this:</p>
<pre><code class="lang-makefile">GREETINGS=<span class="hljs-string">"Hello world!"</span>
MY_NAME=<span class="hljs-string">"Alberto"</span>
</code></pre>
<p>Now we have to create a <code>env.dart</code> file where we can define our constants:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:envied/envied.dart'</span>;

<span class="hljs-keyword">part</span> <span class="hljs-string">'env.g.dart'</span>;

<span class="hljs-comment">//Here you can specify the path to your .env file</span>
<span class="hljs-comment">//  relative to the project root</span>
<span class="hljs-meta">@Envied</span>(path: <span class="hljs-string">'.env'</span>)
<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Env</span> </span>{
  <span class="hljs-comment">//The ofuscate flag lets you make your variables more</span>
  <span class="hljs-comment">// secure through obfuscation</span>
  <span class="hljs-meta">@EnviedField</span>(varName: <span class="hljs-string">'GREETINGS'</span>, obfuscate: <span class="hljs-keyword">true</span>)
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> greetings = _Env.greetings;
  <span class="hljs-meta">@EnviedField</span>(varName: <span class="hljs-string">'MY_NAME'</span>, obfuscate: <span class="hljs-keyword">true</span>)
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> myName = _Env.myName;
}
</code></pre>
<p>Now we can do the build step and let ENVied generate the class for us, so let's run:</p>
<pre><code class="lang-bash">flutter pub run build_runner build --delete-conflicting-outputs
</code></pre>
<p>ENVied will generate a file named <code>env.g.dart</code> alongside <code>env.dart</code> with pretty much this content:</p>
<pre><code class="lang-dart"><span class="hljs-comment">// GENERATED CODE - DO NOT MODIFY BY HAND</span>
<span class="hljs-keyword">part</span> of <span class="hljs-string">'env.dart'</span>;
<span class="hljs-comment">// *****************************************************</span>
<span class="hljs-comment">// EnviedGenerator</span>
<span class="hljs-comment">// *****************************************************</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">_Env</span> </span>{
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">const</span> <span class="hljs-built_in">List</span>&lt;<span class="hljs-built_in">int</span>&gt; _enviedkeygreetings = [
    <span class="hljs-number">3271495377</span>, <span class="hljs-number">3997315090</span>, <span class="hljs-number">436058207</span>, <span class="hljs-number">3553787292</span>, <span class="hljs-number">3538777736</span>,
    <span class="hljs-number">955590460</span>, <span class="hljs-number">3819871908</span>, <span class="hljs-number">4039201348</span>, <span class="hljs-number">2424541315</span>, <span class="hljs-number">3686169803</span>,
    <span class="hljs-number">1299522498</span>, <span class="hljs-number">1263434759</span>
  ];
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">const</span> <span class="hljs-built_in">List</span>&lt;<span class="hljs-built_in">int</span>&gt; _envieddatagreetings = [
    <span class="hljs-number">3271495321</span>, <span class="hljs-number">3997315191</span>, <span class="hljs-number">436058163</span>, <span class="hljs-number">3553787376</span>, <span class="hljs-number">3538777831</span>,
    <span class="hljs-number">955590428</span>, <span class="hljs-number">3819871955</span>, <span class="hljs-number">4039201323</span>, <span class="hljs-number">2424541425</span>, <span class="hljs-number">3686169767</span>,
    <span class="hljs-number">1299522470</span>, <span class="hljs-number">1263434790</span>
  ];
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> greetings = <span class="hljs-built_in">String</span>.fromCharCodes(
    <span class="hljs-built_in">List</span>.generate(_envieddatagreetings.length, (i) =&gt; i, growable: <span class="hljs-keyword">false</span>)
        .map((i) =&gt; _envieddatagreetings[i] ^ _enviedkeygreetings[i])
        .toList(growable: <span class="hljs-keyword">false</span>),
  );
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">const</span> <span class="hljs-built_in">List</span>&lt;<span class="hljs-built_in">int</span>&gt; _enviedkeymyName = [
    <span class="hljs-number">3026637516</span>, <span class="hljs-number">1908999005</span>, <span class="hljs-number">3526437322</span>, <span class="hljs-number">2478128297</span>, <span class="hljs-number">2753058997</span>,
    <span class="hljs-number">855764648</span>, <span class="hljs-number">1111676782</span>
  ];
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">const</span> <span class="hljs-built_in">List</span>&lt;<span class="hljs-built_in">int</span>&gt; _envieddatamyName = [
    <span class="hljs-number">3026637453</span>, <span class="hljs-number">1908998961</span>, <span class="hljs-number">3526437288</span>, <span class="hljs-number">2478128332</span>, <span class="hljs-number">2753059015</span>,
    <span class="hljs-number">855764700</span>, <span class="hljs-number">1111676673</span>
  ];
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> myName = <span class="hljs-built_in">String</span>.fromCharCodes(
    <span class="hljs-built_in">List</span>.generate(_envieddatamyName.length, (i) =&gt; i, growable: <span class="hljs-keyword">false</span>)
        .map((i) =&gt; _envieddatamyName[i] ^ _enviedkeymyName[i])
        .toList(growable: <span class="hljs-keyword">false</span>),
  );
}
</code></pre>
<p>Before proceeding it is good to exclude from version control the <code>.env</code> and <code>env.g.dart</code> files that contain all our variables, to do this simply add to the <code>.gitignore</code> file:</p>
<pre><code class="lang-makefile"><span class="hljs-comment">#Envied</span>
*.env
env.g.dart
</code></pre>
<h3 id="heading-app-code">App Code</h3>
<p>At this point, we can create a small example app that shows how to use our environment variables and call them within the code, so create a <code>main.dart</code> file with the following code:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter/material.dart'</span>;

<span class="hljs-keyword">import</span> <span class="hljs-string">'env.dart'</span>;

<span class="hljs-keyword">void</span> main() {
  runApp(<span class="hljs-keyword">const</span> MyApp());
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyApp</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
  <span class="hljs-keyword">const</span> MyApp({<span class="hljs-keyword">super</span>.key});

  <span class="hljs-meta">@override</span>
  Widget build(BuildContext context) {
    <span class="hljs-keyword">return</span> MaterialApp(
      debugShowCheckedModeBanner: <span class="hljs-keyword">false</span>,
      title: <span class="hljs-string">'ENVied Demo'</span>,
      home: Scaffold(
        appBar: AppBar(
          title: <span class="hljs-keyword">const</span> Text(<span class="hljs-string">"ENVied Demo"</span>),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: &lt;Widget&gt;[
              Text(
                Env.greetings,
              ),
              Text(
                <span class="hljs-string">"Hi, I'm <span class="hljs-subst">${Env.myName}</span>"</span>,
              ),
            ],
          ),
        ),
      ),
    );
  }
}
</code></pre>
<p>As you can see we can call within the code of our app the environment variables we created simply with:</p>
<pre><code class="lang-dart"><span class="hljs-comment">//Import the env class</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'env.dart'</span>;

<span class="hljs-comment">//Use variables</span>
Env.greetings
Env.myName
</code></pre>
<p>The result is something like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1673592242656/1d1e575c-3f82-4df1-823f-644b855250b6.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-conclusions">Conclusions</h3>
<p>In this post, we saw how to secure our environment variables through obfuscation, how to exclude them from version control so they are not exposed in our repositories, and how to generate a Dart class that we can access throughout the code to conveniently use our variables. So we have all the requirements to start developing an app with a good degree of security.</p>
<p>Code strong, Alberto</p>
]]></content:encoded></item><item><title><![CDATA[Change window size on Flutter programmatically]]></title><description><![CDATA[This article will show you how to create a simple Flutter Desktop App with the ability to quickly change the size of the window, which is useful in cases where you need to test different graphic layouts and don't want to change the size of the window...]]></description><link>https://blog.albertobonacina.com/change-window-size-on-flutter-programmatically</link><guid isPermaLink="true">https://blog.albertobonacina.com/change-window-size-on-flutter-programmatically</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Flutter Examples]]></category><category><![CDATA[Dart]]></category><dc:creator><![CDATA[Alberto Bonacina]]></dc:creator><pubDate>Fri, 23 Dec 2022 22:34:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1671124397619/BMKEURSwl.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This article will show you how to create a simple <a target="_blank" href="https://flutter.dev/">Flutter</a> Desktop App with the ability to quickly change the size of the window, which is useful in cases where you need to test different graphic layouts and don't want to change the size of the window by hand by doing the resize with the mouse, doing it automatically allows you to define predefined window sizes and conveniently switch between them with one click.</p>
<p>This article is in the series <a target="_blank" href="https://blog.albertobonacina.com/series/simple-flutter-apps">Simple Flutter Apps</a> where I want to show how to code some simple apps in Flutter to help you get started.</p>
<h3 id="heading-what-we-will-build">What we will build</h3>
<p>We are going to create a simple application using the very useful <a target="_blank" href="https://pub.dev/packages/window_manager">window_manager</a> package with which we can act on the window in which the app is running to do resizing and repositioning. The package supports Windows, macOS and Linux and in this simple example no special control codes have been created, in case we develop the app for other platforms, Android, iOS and Web, it is a good idea to add controls on the execution of the resize code only if the app is running on Desktop.</p>
<p>The dependencies that will help us in the development of the application, are found in the file <code>pubspec.yaml</code>, are:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">dependencies:</span>
  <span class="hljs-string">...</span>
  <span class="hljs-attr">flutter_riverpod:</span> <span class="hljs-string">^2.1.1</span>
  <span class="hljs-attr">window_manager:</span> <span class="hljs-string">^0.2.8</span>
</code></pre>
<ul>
<li><p><a target="_blank" href="https://pub.dev/packages/flutter_riverpod">flutter_riverpod</a>: library with which the state of the application is maintained, which in this case is the size of the window;</p>
</li>
<li><p><a target="_blank" href="https://pub.dev/packages/window_manager">window_manager</a>: a library that takes care of the window resize through a <code>Size()</code> class to pass the <code>width</code> and <code>height</code> to;</p>
</li>
</ul>
<p>The result looks similar to this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671834630384/b6fbc221-77cf-4cd3-b480-e445dd7d0ee5.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-lets-code">Let's code</h3>
<p>You can find all the code in this GitHub repo <a target="_blank" href="https://github.com/polilluminato/simple-flutter-resizewindow">simple-flutter-resizewindow</a> and these are the main parts.</p>
<h4 id="heading-enumswindowsizeenumdart"><code>enums/windowsize_enum.dart</code></h4>
<p>Enum in its <strong>Enhanced</strong> version available from Dart 2.7 with which it is possible to assign multiple properties, named or positional arguments and define custom methods and getters. Specifically, within the enum, I defined keys with which to identify the screen size I want to support by specifying the width and height of the window as well as a description. In this way it is possible to find all the necessary information with the use of only this enum:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">enum</span> WindowSizeEnum {
  mobilePortrait(<span class="hljs-number">400</span>, <span class="hljs-number">890</span>, <span class="hljs-string">"Mobile Portrait"</span>),
  mobileLandscape(<span class="hljs-number">890</span>, <span class="hljs-number">400</span>, <span class="hljs-string">"Mobile Landscape"</span>),
  tabletPortrait(<span class="hljs-number">607</span>, <span class="hljs-number">874</span>, <span class="hljs-string">"Tablet Portrait"</span>),
  tabletLandscape(<span class="hljs-number">874</span>, <span class="hljs-number">607</span>, <span class="hljs-string">"Tablet Landscape"</span>),
  desktop(<span class="hljs-number">1440</span>, <span class="hljs-number">900</span>, <span class="hljs-string">"Desktop"</span>);

  <span class="hljs-keyword">const</span> WindowSizeEnum(<span class="hljs-keyword">this</span>.width, <span class="hljs-keyword">this</span>.height, <span class="hljs-keyword">this</span>.description);
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">double</span> width;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">double</span> height;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> description;
}
</code></pre>
<p>The article I relied on is <a target="_blank" href="https://codewithandrea.com/tips/enums-with-members-dart-2.17">How to Use Enhanced Enums with Members in Dart 2.17</a> on <a target="_blank" href="https://codewithandrea.com/">CodeWithAndrea</a>.</p>
<h4 id="heading-providerwindowsizeproviderdart"><code>provider/windowsize_provider.dart</code></h4>
<p>In this file was defined the class that manages the application state, which is the window size, the provider and the notifier that allows this state to be exposed and modified to the main view from the <code>home_page.dart</code>. The state of the application is based on the <code>WindowSize</code> class, which has a <code>width</code> and a <code>height</code>:</p>
<pre><code class="lang-dart"><span class="hljs-meta">@immutable</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">WindowSize</span> </span>{
  <span class="hljs-keyword">const</span> WindowSize({<span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.width, <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.height});

  <span class="hljs-keyword">final</span> <span class="hljs-built_in">double</span> width;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">double</span> height;

  WindowSize copyWith({<span class="hljs-built_in">double?</span> width, <span class="hljs-built_in">double?</span> height}) {
    <span class="hljs-keyword">return</span> WindowSize(
      width: width ?? <span class="hljs-keyword">this</span>.width,
      height: height ?? <span class="hljs-keyword">this</span>.height,
    );
  }
}
</code></pre>
<p>this class is then used by a <code>StateNotifier</code> to keep track of the state and change it, with the <code>changeSize</code> method, and then expose it via the <code>state</code> to all widgets that need it:</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">WindowSizeNotifier</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StateNotifier</span>&lt;<span class="hljs-title">WindowSize</span>&gt; </span>{
  WindowSizeNotifier() : <span class="hljs-keyword">super</span>(<span class="hljs-keyword">const</span> WindowSize(width: <span class="hljs-number">400</span>, height: <span class="hljs-number">890</span>));

  <span class="hljs-keyword">void</span> changeSize(WindowSize windowSize) {
    state = windowSize;
  }
}
</code></pre>
<p>finally through a <code>StateNotifierProvider</code> we allow the UI to interact with the <code>WindowSizeNotifier</code>:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">final</span> windowSizeProvider =
    StateNotifierProvider&lt;WindowSizeNotifier, WindowSize&gt;((ref) {
  <span class="hljs-keyword">return</span> WindowSizeNotifier();
});
</code></pre>
<h4 id="heading-pageshomepagedart"><code>pages/home_page.dart</code></h4>
<p>A <code>PopupMenuButton</code> has been added to the home page to allow the user to quickly change from one window size to another. When one of the options is chosen, the <code>actionChangeWindowSize</code> method is called, which takes care of calling <code>windowManager</code> to change the window size and update the application state:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">void</span> actionChangeWindowSize(WindowSizeEnum windowSizeEnum) {
      <span class="hljs-comment">//Update window size</span>
      windowManager.setSize(
        Size(
          windowSizeEnum.width,
          windowSizeEnum.height,
        ),
      );
      <span class="hljs-comment">//Read provider and change status</span>
      ref.read(windowSizeProvider.notifier).changeSize(
            WindowSize(
              width: windowSizeEnum.width,
              height: windowSizeEnum.height,
            ),
          );
}
</code></pre>
<h3 id="heading-how-to-improve-it">How to improve it</h3>
<p>As always there are so many ways to improve a demo application like this, the first ones that come to mind are definitely:</p>
<ul>
<li><p>add control code to check which platform the application is running on and then disable the window resize feature because it could not be executed;</p>
</li>
<li><p>in the case of a much more complex application with several pages and sections, it might be useful to move the editing part of the window to a settings-related section, which should only be displayed in development and not in production.</p>
</li>
</ul>
<p>You can find all the app code in this GitHub repo: <a target="_blank" href="https://github.com/polilluminato/simple-flutter-resizewindow">simple-flutter-resizewindow</a>, you can fork, use and modify it as you want, the app uses thein latest Flutter 3.3.10 you can build it on Windows, macOS and Linux.</p>
<p>Code strong, Alberto</p>
<p>Foto di <a target="_blank" href="https://unsplash.com/@usgs?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">USGS</a> su <a target="_blank" href="https://unsplash.com/it/s/foto/change?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></p>
]]></content:encoded></item><item><title><![CDATA[The biggest lesson learned this year for the Dev Retro 2022]]></title><description><![CDATA[In this post, I want to take full advantage of the challenge launched by Hashnode to look back to 2022 with the Dev Retro 2022 and tell what is the biggest lesson I learned this year and which made me a better developer.
This year I fully learned the...]]></description><link>https://blog.albertobonacina.com/the-biggest-lesson-learned-this-year-for-the-dev-retro-2022</link><guid isPermaLink="true">https://blog.albertobonacina.com/the-biggest-lesson-learned-this-year-for-the-dev-retro-2022</guid><category><![CDATA[Java]]></category><category><![CDATA[quarkus]]></category><category><![CDATA[Personal growth  ]]></category><category><![CDATA[personal development]]></category><category><![CDATA[#DevRetro2022]]></category><dc:creator><![CDATA[Alberto Bonacina]]></dc:creator><pubDate>Sat, 10 Dec 2022 23:22:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1670713930936/oCbxDgQU2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this post, I want to take full advantage of the challenge launched by Hashnode to look back to 2022 with the <a target="_blank" href="https://townhall.hashnode.com/announcing-dev-retro-2022">Dev Retro 2022</a> and tell what is the biggest lesson I learned this year and which made me a better developer.</p>
<p>This year I fully learned the meaning of the quote:</p>
<blockquote>
<p>Don't judge a book by its cover</p>
</blockquote>
<p>which in my case concerns a programming language that I have always considered over the years to be "old" and uninteresting, but which in the last year, thanks to the help of a colleague who has opened my eyes, I have learned to appreciate and to use more and more: <strong>Java</strong>.</p>
<h3 id="heading-preamble">Preamble</h3>
<p>Since university, I have always considered Java as a language to keep away from because, erroneously, I considered it as "old", too "enterprise" and far from what was the Hacker spirit to which I wanted to belong. I always tried not to take any course that included it as a language to use to pass the exam. In the only course that I could not avoid and which required a project with the recommended language Java, I asked the professor to be able to do it with another language, at the time I chose PHP, with which I had a fair amount of work experience and which suited me more.</p>
<h3 id="heading-first-approach">First approach</h3>
<p>A few years after finishing university, for a company I worked for, I developed a couple of native applications for Android at the time when Kotlin had just been announced, but the company still didn't want to use this language. My approach with Java had been to live with it for business needs, I was also starting to study Kotlin on my own to no longer need to use Java to develop applications.</p>
<h3 id="heading-java-fulltime">Java FullTime</h3>
<p>Currently, I am involved in the maintenance and development of Java applications with <a target="_blank" href="https://spring.io/">Spring</a> and I have been dealing with Java code, not always written by me, for about two years but until the middle of 2022, my relationship has always been one of love/hate with this language.</p>
<h3 id="heading-the-lighting">The lighting</h3>
<p>Since mid-2022, on the other hand, everything has changed thanks to the new entry into the team of which I am part of a colleague who has been working with Java for 20 years and who has opened my eyes to a whole series of Frameworks, libraries, patterns that I did not know but they completely and forever changed my opinion of Java and its ecosystem.</p>
<p><em>They made me change so much that, up until a year ago, I would have done any backend application that provides APIs and interacts with a DB with Node.js, now I wouldn't think about it for a moment and I would do it with one of <a target="_blank" href="https://spring.io/projects/spring-boot">Spring Boot</a> and <a target="_blank" href="https://quarkus.io/">Quarkus</a></em>.</p>
<p>As proof of the fact that I have changed my mind, I recently developed two applications that interact with Telegram Bots, and I made them both with Quarkus, one of them I talked about here: <a target="_blank" href="https://blog.albertobonacina.com/save-bookmarks-to-notion-database-with-telegram-and-quarkus">Save Bookmarks to Notion Database with Telegram and Quarkus</a>.</p>
<p>The conversations and articles that I've been reading the most in the last weeks always refer in some way to Java and in particular:</p>
<ul>
<li><a target="_blank" href="https://vladmihalcea.com/">Vlad Mihalcea</a>: an institution regarding the whole world of persistence and databases in Java;</li>
<li><a target="_blank" href="https://www.baeldung.com/">Baeldung</a>: if you look for any Java and Spring guide 9 times out of 10 you end up here;</li>
<li><a target="_blank" href="https://www.youtube.com/@amigoscode">Amigoscode</a>: a YouTube channel with lots of quality content on Java;</li>
<li><a target="_blank" href="https://www.youtube.com/@GiuseppeScaramuzzino">Giuseppe Scaramuzzino</a>: I learned a lot from his videos on Quarkus;</li>
<li><a target="_blank" href="https://twitter.com/maciejwalkowiak">Maciej Walkowiak</a> and <a target="_blank" href="https://twitter.com/therealdanvega">Dan Vega</a> on Twitter.</li>
</ul>
<h2 id="heading-conclusions">Conclusions</h2>
<p>This year I learned how I had always had the wrong idea about Java because there had never been anyone who guided me and showed me what good I could find in its ecosystem. I learned how important it is to have a colleague, in this case, a mentor, who can open your eyes and give you another point of view on things because often your first opinion can be wrong and you could miss out on a great opportunity for personal and professional growth.
I won't name him because I know he wouldn't want to but when he reads the article he will surely understand that I'm talking about him.
I am looking forward to the new challenges that 2023 will bring and its new opportunities to grow.</p>
<p>Code strong,
Alberto</p>
<p>Credits: <a href="https://www.freepik.com/free-vector/retro-sunburst-rays-background_10316591.htm#page=3&amp;query=retro%20background&amp;position=2&amp;from_view=search&amp;track=sph">Image by starline</a> on Freepik</p>
]]></content:encoded></item><item><title><![CDATA[Save Bookmarks to Notion Database with Telegram and Quarkus]]></title><description><![CDATA[Hi everyone, in this post, I want to show you how I experimented with the Quarkus framework to solve a problem I had with saving articles to read them later from different PCs and from my smartphone.
Background
For work and in my personal life I use ...]]></description><link>https://blog.albertobonacina.com/save-bookmarks-to-notion-database-with-telegram-and-quarkus</link><guid isPermaLink="true">https://blog.albertobonacina.com/save-bookmarks-to-notion-database-with-telegram-and-quarkus</guid><category><![CDATA[telegram]]></category><category><![CDATA[telegram bot]]></category><category><![CDATA[quarkus]]></category><category><![CDATA[Java]]></category><category><![CDATA[notion]]></category><dc:creator><![CDATA[Alberto Bonacina]]></dc:creator><pubDate>Wed, 26 Oct 2022 20:50:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1666816626530/3D09V2QNx.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hi everyone, in this post, I want to show you how I experimented with the <a target="_blank" href="https://quarkus.io/">Quarkus framework</a> to solve a problem I had with saving articles to <strong>read them later</strong> from different PCs and from my smartphone.</p>
<h2 id="heading-background">Background</h2>
<p>For work and in my personal life I use 3 devices:</p>
<ul>
<li>Business PC with <a target="_blank" href="https://ubuntu.com/">Ubuntu</a></li>
<li>Personal PC with <a target="_blank" href="https://pop.system76.com/">Pop! _OS</a></li>
<li>Smartphone with Android</li>
</ul>
<p>On all these devices when I browse it often happens that I want to save articles, web pages, and guides to read later. I have been using <a target="_blank" href="https://www.notion.so/">Notion</a> for some time to organize my bookmarks list, in which I created a database where I save my links, add tags, date, and if I have already read them or not.
But using 3 different devices I wanted a quick way to save the links directly in Notion without having to open the web or the Android app, create a new line, choose tags, and put a title and a date.</p>
<p>So I thought of creating a simple <a target="_blank" href="https://core.telegram.org/bots">Telegram Bot</a> to which I can send a message and it, using the Notion APIs, saves the web page in my database. The Bot is powered by a <strong>Quarkus</strong> application.</p>
<p>Let's see how I did it!</p>
<h2 id="heading-application">Application</h2>
<p>The source code of the application is available in this repo on GitHub: <a target="_blank" href="https://github.com/polilluminato/telegram2notion-quarkus">Telegram2Notion Quarkus</a> released under <a target="_blank" href="https://github.com/polilluminato/telegram2notion-quarkus/blob/main/LICENSE.md">MIT license</a>.</p>
<p>Once configured, the result is what you can see in this video:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://vimeo.com/763926082">https://vimeo.com/763926082</a></div>
<p>Here is some information about the project:</p>
<ul>
<li>to interact with the telegram bot I used the library: <a target="_blank" href="https://mvnrepository.com/artifact/org.telegram/telegrambots">Telegram Bots</a> which allows you to interact with a Telegram bot from a Java application;</li>
<li>to interact with the Notion API I used the documentation here: <a target="_blank" href="https://developers.notion.com/reference/intro">Introduction</a> and the <a target="_blank" href="https://www.postman.com/notionhq/">Postman collection</a>;</li>
<li>to create the app documentation I used <a target="_blank" href="https://docs.page/">Docs.page</a> by <a target="_blank" href="https://invertase.io/">Invertase</a>;</li>
<li>the app documentation is available at <a target="_blank" href="https://docs.page/polilluminato/telegram2notion-quarkus">Telegram2Notion Quarkus Docs</a>;</li>
<li>I used <a target="_blank" href="https://jsoup.org/">jsoup: Java HTML Parser</a> to obtain information on the webpage sent to the bot;</li>
<li>to get information on the status of the app I have enabled <a target="_blank" href="https://quarkus.io/guides/smallrye-health">Quarkus SmallRye Health</a></li>
</ul>
<p>The general operation is schematized as follows:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666815342165/mDWN9Ng-i.jpg" alt="new-link-to-save.jpg" /></p>
<h2 id="heading-future">Future</h2>
<p>You can always follow the development of the application by referring to the repo on GitHub: <a target="_blank" href="https://github.com/polilluminato/telegram2notion-quarkus">Telegram2Notion Quarkus</a> and on the <a target="_blank" href="https://github.com/polilluminato/telegram2notion-quarkus/issues">issues page</a>, currently the next feature to be implemented is the possibility to specify a custom title for the link you want to save (<a target="_blank" href="https://github.com/polilluminato/telegram2notion-quarkus/issues/5">#5</a>).</p>
<p>Bye, Alberto</p>
]]></content:encoded></item><item><title><![CDATA[Wassword: wonderful password generator built in Flutter]]></title><description><![CDATA[Hi, in this post I want to show you one of the most loved side projects that a long time ago introduce me to Flutter. In these years I made lots of changes and experiments with this project and I want to share with you the final result to date.
Wassw...]]></description><link>https://blog.albertobonacina.com/wassword-wonderful-password-generator-built-in-flutter</link><guid isPermaLink="true">https://blog.albertobonacina.com/wassword-wonderful-password-generator-built-in-flutter</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Flutter Examples]]></category><category><![CDATA[Flutter SDK]]></category><category><![CDATA[side project]]></category><category><![CDATA[Android]]></category><dc:creator><![CDATA[Alberto Bonacina]]></dc:creator><pubDate>Sun, 24 Oct 2021 13:11:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1635080856205/-8XAYqp_m.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hi, in this post I want to show you one of the most loved side projects that a long time ago introduce me to Flutter. In these years I made lots of changes and experiments with this project and I want to share with you the final result to date.</p>
<p>Wassword is a password generator and as said in its description:</p>
<blockquote>
<p>With Wassword you can easily generate complex passwords and use them for your online accounts. Choose length and chars to be used and generate your passwords safely.
Everything works offline and nothing is shared, your safety comes first.</p>
</blockquote>
<p>so with Wassword you can create passwords with <strong>Numbers</strong>, <strong>Lower case letters</strong>, <strong>Upper case letters</strong>, and <strong>Symbols</strong> from <strong>8 to 32 chars</strong>. Once you created your password you can copy it and use with your account, share it and there's no limit on how many password you can create. </p>
<p>These are some screenshots that show its functionality:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1634707998186/zTxCAlyqI.png" alt="wassword-screenshots.png" /></p>
<p>Wassword is Open Source with <a target="_blank" href="https://opensource.org/licenses/MIT">MIT License</a> and you can find the repo on GitHub with all the source code: <a target="_blank" href="https://github.com/polilluminato/wassword-flutter">wassword-flutter</a>.</p>
<h2 id="project-structure">Project Structure</h2>
<p>Let's dive a little into the project structure to explain how I organize all the code and what packages I used. To start these are my dependencies:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">dependencies:</span>
  <span class="hljs-string">...</span>
  <span class="hljs-attr">bloc:</span> <span class="hljs-string">^7.2.1</span>
  <span class="hljs-attr">equatable:</span> <span class="hljs-string">^2.0.3</span>
  <span class="hljs-attr">flutter_bloc:</span> <span class="hljs-string">^7.3.0</span>
  <span class="hljs-attr">fluttertoast:</span> <span class="hljs-string">^8.0.8</span>
  <span class="hljs-attr">google_fonts:</span> <span class="hljs-string">^2.1.0</span>
  <span class="hljs-attr">share_plus:</span> <span class="hljs-string">^2.1.4</span>
  <span class="hljs-attr">url_launcher:</span> <span class="hljs-string">^6.0.10</span>

<span class="hljs-attr">dev_dependencies:</span>
  <span class="hljs-string">...</span>
  <span class="hljs-attr">flutter_launcher_icons:</span> <span class="hljs-string">^0.9.2</span>
  <span class="hljs-attr">flutter_native_splash:</span> <span class="hljs-string">^1.2.3</span>
</code></pre>
<p>I use the <a target="_blank" href="https://bloclibrary.dev/#/">bloc package</a> to manage the state of the app and I choose to go with one <a target="_blank" href="https://bloclibrary.dev/#/coreconcepts?id=cubit">Cubit</a> for its simplicity because my state is the password that I want to show and all the password characteristics like number of chars, numbers and so on. </p>
<p>The other packages are pretty standard: <a target="_blank" href="https://pub.dev/packages/google_fonts">customize the font</a>, <a target="_blank" href="https://pub.dev/packages/share_plus">share generated password</a>, <a target="_blank" href="https://pub.dev/packages/url_launcher">open links</a>, <a target="_blank" href="https://pub.dev/packages/flutter_launcher_icons">create app icon</a> and <a target="_blank" href="https://pub.dev/packages/flutter_native_splash">create splash screen</a>.</p>
<p>This is the structure that I used to manage the code in the <strong>lib</strong> folder and keep the same stuff in the same place:</p>
<ul>
<li><strong>cubit</strong>: in this folder, I put the cubit and the cubit state that lets me manage password characteristics. To change the state I create one method for every characteristic that I want to change, so: <code>changeLowercase</code>, <code>changeUppercase</code> and so on;</li>
<li><strong>pages</strong>: folder where I put the code for the two pages of the application, both stateless widget, one for the main page with the password creation and one for the about page where I put some information about myself and my social account;</li>
<li><strong>styles</strong>: folder where I create variables to theme the app and to make the design consistent; </li>
<li><strong>ui</strong>: folder where I put some reusable UI components across the app like buttons and rows;</li>
<li><strong>utils</strong>: in this folder, there's the function that generates the password based on the selected options.</li>
</ul>
<h2 id="takeaways">Takeaways</h2>
<p>There are many takeaways from this app but two of them that I want to recall are related to the password generator and the slider to set the number of chars in the password. </p>
<p>To generate the password I used the generatePassword method inside <code>password_generator.dart</code> file in <code>lib/utils</code></p>
<pre><code class="lang-dart"><span class="hljs-comment">/*
 * @desc Function to generate passwords based on some criteria
 * @param bool isWithLetters: password must contain letters
 * @param bool isWithUppercase: password must contain uppercase letters
 * @param bool isWithNumbers: password must contain numbers
 * @param bool isWithSpecial: password must contain special chars
 * @param int _numberCharPassword: password length
 * @return string: new password
 */</span>
<span class="hljs-built_in">String</span> generatePassword(
    {<span class="hljs-keyword">required</span> <span class="hljs-built_in">bool</span> isWithLowercase,
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">bool</span> isWithUppercase,
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">bool</span> isWithNumbers,
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">bool</span> isWithSpecial,
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">int</span> numberCharPassword}) {
  <span class="hljs-built_in">String</span> _lowerCaseLetters = <span class="hljs-string">"abcdefghijklmnopqrstuvwxyz"</span>;
  <span class="hljs-built_in">String</span> _upperCaseLetters = <span class="hljs-string">"ABCDEFGHIJKLMNOPQRSTUVWXYZ"</span>;
  <span class="hljs-built_in">String</span> _numbers = <span class="hljs-string">"0123456789"</span>;
  <span class="hljs-built_in">String</span> _special = <span class="hljs-string">"@#=+!£\$%&amp;?[](){}-_"</span>;

  <span class="hljs-built_in">String</span> _allowedChars = <span class="hljs-string">""</span>;

  _allowedChars += (isWithLowercase ? _lowerCaseLetters : <span class="hljs-string">''</span>);
  _allowedChars += (isWithUppercase ? _upperCaseLetters : <span class="hljs-string">''</span>);
  _allowedChars += (isWithNumbers ? _numbers : <span class="hljs-string">''</span>);
  _allowedChars += (isWithSpecial ? _special : <span class="hljs-string">''</span>);

  <span class="hljs-keyword">if</span> (_allowedChars.length == <span class="hljs-number">0</span>) {
    <span class="hljs-keyword">return</span> <span class="hljs-string">''</span>;
  }

  <span class="hljs-comment">//If I can create a password because I've got some char to use</span>
  <span class="hljs-built_in">int</span> i = <span class="hljs-number">0</span>;
  <span class="hljs-built_in">String</span> _result = <span class="hljs-string">""</span>;
  <span class="hljs-keyword">while</span> (i &lt; numberCharPassword) {
    <span class="hljs-built_in">int</span> randomInt = Random.secure().nextInt(_allowedChars.length);
    _result += _allowedChars[randomInt];
    i++;
  }

  <span class="hljs-keyword">return</span> _result;
}
</code></pre>
<p>To style the Slider I use this wonderful article on Medium: <a target="_blank" href="https://medium.com/flutter-community/flutter-sliders-demystified-4b3ea65879c">Flutter: Sliders DeMystified</a> where I use a combination of <a target="_blank" href="https://api.flutter.dev/flutter/material/SliderTheme-class.html">SliderTheme</a> and <a target="_blank" href="https://api.flutter.dev/flutter/material/SliderComponentShape-class.html">SliderComponentShape</a> to integrate the slider inside the app's theme. You can find all the code in the <code>pages/home_page.dart</code> and <code>ui/custom_slider_thumb_circle.dart</code>.</p>
<h2 id="download-and-use">Download and Use</h2>
<p>You can download Wassword from the Play Store: <a target="_blank" href="https://play.google.com/store/apps/details?id=com.albertobonacina.wassword">Wassword - Wonderful Password Generator</a> or you can use it on the web at this link: <a target="_blank" href="https://wassword.albertobonacina.com/#/">Wassword Web</a>, the web version is not optimized for the desktop but it has got all the functionalities of the Android version.</p>
<p>Bye,
Alberto</p>
]]></content:encoded></item><item><title><![CDATA[Building a Post Scheduling App with HarperDB & Flutter]]></title><description><![CDATA[Hi everyone, in this article I want to describe my project for the HarperDB Hackathon here on Hashnode. When I saw for the first time the Hashnode Hackathon in collaboration with HarperDB I immediately started thinking about how I can use HarperDB, i...]]></description><link>https://blog.albertobonacina.com/building-a-post-scheduling-app-with-harperdb-and-flutter</link><guid isPermaLink="true">https://blog.albertobonacina.com/building-a-post-scheduling-app-with-harperdb-and-flutter</guid><category><![CDATA[Flutter]]></category><category><![CDATA[hackathon]]></category><category><![CDATA[Flutter Examples]]></category><category><![CDATA[HarperDB Hackathon]]></category><dc:creator><![CDATA[Alberto Bonacina]]></dc:creator><pubDate>Tue, 29 Jun 2021 04:32:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1624912489954/VYa1NACm6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hi everyone, in this article I want to describe my project for the HarperDB Hackathon here on Hashnode. When I saw for the first time the Hashnode Hackathon in collaboration with HarperDB I immediately started thinking about how I can use HarperDB, its services, and APIs. </p>
<p>I look around my needs and I started working on a project to solve one of my problems, that I think other developers on Hashnode also have:</p>
<blockquote>
<p><strong>planning posts scheduling</strong> and <strong>when to share them</strong> on other platforms like Twitter, Reddit, Facebook, and LinkedIn</p>
</blockquote>
<p>Obviously, I want to create something in <a target="_blank" href="https://flutter.dev/">Flutter</a> and with the HarperDB API, I connected my HarperDB instance with very simple steps.</p>
<h2 id="architecture-and-functionality">Architecture &amp; Functionality</h2>
<p>The architecture of the app is very simple, on the database side, there is only one table to store all the posts' schedule info like title, the text of the post on social media, platform, and date of the share. On HarperDB I create a <code>schedule</code> schema and a <code>post</code> table:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1624854223086/SjClnLyDH.png" alt="harperdb-hashnode-schema-table.png" />
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1624915109696/qp4lFmL1O.png" alt="harperdb-hashnode-post-table.png" /></p>
<p>The JSON that represents the single post schedule is this one:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1624854438258/W407Yoc1j.png" alt="json-post-schedule.png" /></p>
<p>There's my Flutter app on the front-end side that lets you retrieve, create, update, and delete all the posts that you have to schedule. By writing the app in Flutter 2.2 you could run the app natively on Android, iOS, and Web. The result is pretty much like this: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1624856805218/foP5yoHVI.png" alt="mockup-phone-harperdb-hashnode-flutter.png" /></p>
<p>The posts are ordered by date so you could immediately see what's the schedule. In the app, all the CRUD operations are made in pure SQL as described in the documentation: <a target="_blank" href="https://docs.harperdb.io/#b63a6f84-565b-4c54-8b1a-4c596d398e50">SQL Operations</a>.</p>
<p>To connect to HarperDB from our app, and the procedure is similar for all other languages and frameworks, you have to use the instance name and the API key, remember to put them in a <code>.env</code> file, and keep away from git by including it on .gitignore. For more information about that you could read these articles:</p>
<ul>
<li><a target="_blank" href="https://blog.greenroots.info/create-a-serverless-book-library-app-with-harperdb-and-gatsbyjs">Create a serverless book library app with HarperDB and Gatsbyjs</a> by <a class="user-mention" href="https://hashnode.com/@atapas">Tapas Adhikary</a></li>
<li><a target="_blank" href="https://catalins.tech/build-a-rest-api-with-harperdb-and-fastifyjs">Build A REST API With HarperDB and FastifyJS</a> by <a class="user-mention" href="https://hashnode.com/@Catalinpit">Catalin Pit</a></li>
<li><a target="_blank" href="https://piyushsinha.tech/harperdb-instance-with-react">HarperDB Instance w/ React</a> by <a class="user-mention" href="https://hashnode.com/@sinhapiyush">Piyush Sinha</a></li>
<li><a target="_blank" href="https://lo-victoria.com/curate-top-programming-blogs-with-react-and-harperdb">Curate Top Programming Blogs with React and HarperDB</a> by <a class="user-mention" href="https://hashnode.com/@victoria">Victoria Lo</a></li>
</ul>
<h2 id="code-info">Code info</h2>
<p>As said earlier the app is built with Flutter 2.2 with support for Android, iOS, and Web, and you can find all the code in this GitHub repo: <a target="_blank" href="https://github.com/polilluminato/harperdb-hashnode-hackathon">harperdb-hashnode-hackathon</a> with <a target="_blank" href="https://choosealicense.com/licenses/mit/">MIT License</a>. The project structure is:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1624857113749/6mmU7lZeJ.png" alt="project-structure-harperdb-hashnode-flutter.png" /></p>
<ul>
<li><strong>models</strong>: models to map the table on HarperDB to Dart Class;</li>
<li><strong>pages</strong>: screens inside the app. The app has only two screens one for the list of the post schedule and one for the single post. I use the same page for the creation and update of a post;</li>
<li><strong>repository/schedule_repository.dart</strong>: main class to interact with HarperDB API;</li>
<li><strong>ui/post_row.dart</strong>: personalization of the row of the single post inside the list in the <code>home_page</code>.</li>
</ul>
<p>To make the project work you need to create a <code>.env</code> file in the project root, that was not added to version control with git, like this:</p>
<pre><code><span class="hljs-attr">HARPER_DB_SECRET_KEY</span>=<span class="hljs-string">'your-secret-key'</span>
<span class="hljs-attr">HARPER_DB_URL</span>=<span class="hljs-string">'https://your-istance-name.harperdbcloud.com'</span>
</code></pre><p>When you run the app, on the homepage you could find the list of all the posts schedule with information on the day, platform to share, title, text, and link to the post. By tapping on a single line you go to the detail page where it's possible to modify all the info, save them to the DB or delete the post scheduling. On the homepage, if you tap on the violet FAB in the bottom right you could create a new post scheduling, and with the refresh button on the top right on the homepage, you sync all the info on the HarperDB with the App. </p>
<h4 id="models">Models</h4>
<p>The <code>post_model.dart</code> is responsible for the translation between the JSON that represents the post schedule and the Dart class, in that class there is the definition of all the fields and the <code>Post.fromJson</code> function converts the JSON from HarperDB in the Post Class used inside the app:</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Post</span> </span>{
  <span class="hljs-built_in">String</span> id;
  <span class="hljs-built_in">String</span> link;
  <span class="hljs-built_in">String</span> platform;
  <span class="hljs-built_in">DateTime</span> postDate;
  <span class="hljs-built_in">String</span> text;
  <span class="hljs-built_in">String</span> title;

  Post({
    <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.id,
    <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.link,
    <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.platform,
    <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.postDate,
    <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.text,
    <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.title,
  });

  <span class="hljs-keyword">factory</span> Post.fromJson(<span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">dynamic</span>&gt; json) {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Post(
      id: json[<span class="hljs-string">'id'</span>] <span class="hljs-keyword">as</span> <span class="hljs-built_in">String</span>,
      link: json[<span class="hljs-string">'link'</span>] <span class="hljs-keyword">as</span> <span class="hljs-built_in">String</span>,
      platform: json[<span class="hljs-string">'platform'</span>] <span class="hljs-keyword">as</span> <span class="hljs-built_in">String</span>,
      postDate: <span class="hljs-built_in">DateTime</span>.parse(json[<span class="hljs-string">'post_date'</span>]),
      text: json[<span class="hljs-string">'text'</span>] <span class="hljs-keyword">as</span> <span class="hljs-built_in">String</span>,
      title: json[<span class="hljs-string">'title'</span>] <span class="hljs-keyword">as</span> <span class="hljs-built_in">String</span>,
    );
  }
}
</code></pre>
<h4 id="harperdb-api">HarperDB API</h4>
<p>All the code to interact with the HarperDB API is in the <code>schedule_repository.dart</code> Class where I create an <code>http.Client</code> and with the <code>flutter_dotenv</code> package I make calls to HarperDB with my <code>HARPER_DB_SECRET_KEY</code> and <code>HARPER_DB_URL</code>. All the functions that correspond to the CRUD (Create, Read, Update, Delete) operations return a Future because are asynchronous and the structure is:</p>
<pre><code class="lang-dart"><span class="hljs-comment">//All calls to HarperDB have been created asynchronously because it is not possible </span>
<span class="hljs-comment">//  to know when a response will arrive which is therefore defined as a Future</span>
Future&lt;responseType&gt; actionToPerform(variable) <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-comment">//Create a POST request with the http Client</span>
        <span class="hljs-keyword">final</span> response = <span class="hljs-keyword">await</span> _client.post(
            <span class="hljs-comment">//Set the URL to call</span>
            <span class="hljs-built_in">Uri</span>.parse(<span class="hljs-string">'<span class="hljs-subst">${dotenv.env[<span class="hljs-string">'HARPER_DB_URL'</span>]}</span>'</span>), 
            <span class="hljs-comment">//Set headers like the authentication and the content-type</span>
            headers: {
                HttpHeaders.authorizationHeader:
                    <span class="hljs-string">'Basic <span class="hljs-subst">${dotenv.env[<span class="hljs-string">'HARPER_DB_SECRET_KEY'</span>]}</span>'</span>,
                HttpHeaders.contentTypeHeader: <span class="hljs-string">'application/json'</span>
            },
            <span class="hljs-comment">//Encode the JSON to send to HarperDB</span>
            body: json.encode({
                <span class="hljs-comment">//Operation Mode to intercat with HarperDB</span>
                <span class="hljs-string">"operation"</span>: <span class="hljs-string">"sql"</span>,
                <span class="hljs-comment">//Query to execute</span>
                <span class="hljs-string">"SQL"</span>: <span class="hljs-string">"...."</span>
            }),
        );
        <span class="hljs-comment">//Handle the responde from HarperDB</span>
        <span class="hljs-keyword">if</span> (response.statusCode == <span class="hljs-number">200</span>) {
            <span class="hljs-keyword">return</span> ok_result;
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">return</span> ko_result;
        }
    } <span class="hljs-keyword">catch</span> (_) {
        <span class="hljs-keyword">return</span> ko_result;
    }
}
</code></pre>
<h4 id="packages">Packages</h4>
<p>To simplify the development of some functionality, the following packages have been included in the project:</p>
<ul>
<li><a target="_blank" href="https://pub.dev/packages/datetime_picker_formfield">datetime_picker_formfield</a>: used to show a datetime picker on the single schedule post to set date and time where to publish the post or share it on social media;</li>
<li><a target="_blank" href="https://pub.dev/packages/flutter_dotenv">flutter_dotenv</a>: used to load configuration variable from a <code>.env</code> file;</li>
<li><a target="_blank" href="https://pub.dev/packages/flutter_styled_toast">flutter_styled_toast</a>: used to show a simple toast when the app completes actions like save, update, delete posts;</li>
<li><a target="_blank" href="https://pub.dev/packages/google_fonts">google_fonts</a>: used to customize the look and feel of the app with custom fonts;</li>
<li><a target="_blank" href="https://pub.dev/packages/http">http</a>: used to make POST requests to the HarperDB API;</li>
<li><a target="_blank" href="https://pub.dev/packages/intl">intl</a>: used to localize and format dates;</li>
<li><a target="_blank" href="https://pub.dev/packages/url_strategy">url_strategy</a>: used to set the web URL strategy, in particular, used to remove the # in the URL of the web app.</li>
</ul>
<h2 id="improvements">Improvements</h2>
<p>Obviously, there's a lot of improvement that can be made, I share here some ideas that came to my mind during development, or that were suggested to me, that it could be included in future versions of the application, which for now is to be considered as a proof of concept of what is possible with HarperDB and Flutter:</p>
<ul>
<li>more customization on the UI (like dark mode 😉)</li>
<li>better management of app refreshes when switching from one screen to another. Now you have to tap on the update button on the top left of the home page to sync information between HarperDB and the app</li>
<li>implement a single post registry and subsequent scheduling by choosing only the date and platform. In this way, you don' have to put the title, link on all the scheduling posts because the registry is unique</li>
<li>allow, through a login, multiple users to create their own personal data and then manage their scheduling</li>
<li>publish the application on the Android, iOS stores and make it publicly available on the internet. All this is possible directly with Flutter making the application truly multi-platform and available to everyone on any device</li>
</ul>
<p>An improvement that can be made and that is not directly linked to this app, in particular, is the possibility of developing a package for Flutter to be published on <a target="_blank" href="https://pub.dev/">pub.dev</a> with which to interface directly with the HarperDB API in a simpler way and cover the most possible of API calls in the documentation; in this regard, we could certainly establish the discussion directly with the developers of HarperDB to understand if there is interest.</p>
<p>Bye, Alberto</p>
]]></content:encoded></item><item><title><![CDATA[Create a Simple Responsive GridView with Flutter]]></title><description><![CDATA[In this post, I want to guide you in a Simple Flutter App by making a responsive GridView. This is useful because now Flutter supports web apps and make a responsive UI a must-have in the web world. This article is in the series Simple Flutter Apps w...]]></description><link>https://blog.albertobonacina.com/create-a-simple-responsive-gridview-with-flutter</link><guid isPermaLink="true">https://blog.albertobonacina.com/create-a-simple-responsive-gridview-with-flutter</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Flutter Examples]]></category><category><![CDATA[Flutter SDK]]></category><category><![CDATA[Flutter Widgets]]></category><category><![CDATA[responsive design]]></category><dc:creator><![CDATA[Alberto Bonacina]]></dc:creator><pubDate>Sat, 12 Jun 2021 06:08:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1623477809095/Tt_4UICaI.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this post, I want to guide you in a Simple Flutter App by making a responsive GridView. This is useful because now Flutter supports web apps and make a responsive UI a must-have in the web world. This article is in the series <a target="_blank" href="https://blog.albertobonacina.com/series/simple-flutter-apps">Simple Flutter Apps</a> where I want to show how to code some simple apps in Flutter to help you get started.</p>
<h3 id="what-we-will-build">What we will build</h3>
<p>We build a simple flutter app to implement a responsive GridView using an awesome package by <a target="_blank" href="https://twitter.com/lets4r">Romain Rastel @lets4r</a> called <a target="_blank" href="https://pub.dev/packages/flutter_staggered_grid_view">flutter_staggered_grid_view</a>, a staggered grid view which supports multiple columns with rows of varying sizes. By making this app we will learn:</p>
<ul>
<li>display different layouts based on the screen size;</li>
<li>use a very well know package in the Flutter world;</li>
<li>make a simple card UI layout like Pinterest.</li>
</ul>
<p>The final result in different screen sizes will be:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1623410562677/j4rPvEeqQ.gif" alt="FlutterResponsiveGridview.gif" /></p>
<h3 id="lets-code">Let's code</h3>
<p>First of all, we have to import the <a target="_blank" href="https://pub.dev/packages/flutter_staggered_grid_view">flutter_staggered_grid_view</a> package so we have to include it in the pubspec.yaml</p>
<pre><code class="lang-yaml"><span class="hljs-attr">dependencies:</span>
  <span class="hljs-string">...</span>
  <span class="hljs-attr">flutter_staggered_grid_view:</span> <span class="hljs-string">^0.4.0</span>
</code></pre>
<p>After that to implement a responsive layout we have to use a LayoutBuilder that builds a widget tree that depends on the parent widget's size, so we can define a set of widths, and based on them we can change the UI. Let's first define the widths</p>
<pre><code class="lang-dart"><span class="hljs-keyword">const</span> kMobileBreakpoint = <span class="hljs-number">576</span>;
<span class="hljs-keyword">const</span> kTabletBreakpoint = <span class="hljs-number">1024</span>;
<span class="hljs-keyword">const</span> kDesktopBreakPoint = <span class="hljs-number">1366</span>;
</code></pre>
<p>then we can set up our LayoutBuilder like this</p>
<pre><code class="lang-dart">LayoutBuilder(
  builder: (context, dimens) {
    <span class="hljs-keyword">if</span> (dimens.maxWidth &lt;= kMobileBreakpoint) {
      <span class="hljs-keyword">return</span> CustomGridView(columnRatio: <span class="hljs-number">6</span>,);
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (dimens.maxWidth &gt; kMobileBreakpoint &amp;&amp;
        dimens.maxWidth &lt;= kTabletBreakpoint) {
      <span class="hljs-keyword">return</span> CustomGridView(columnRatio: <span class="hljs-number">4</span>,);
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (dimens.maxWidth &gt; kTabletBreakpoint &amp;&amp;
        dimens.maxWidth &lt;= kDesktopBreakPoint) {
      <span class="hljs-keyword">return</span> CustomGridView(columnRatio: <span class="hljs-number">3</span>,);
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">return</span> CustomGridView(columnRatio: <span class="hljs-number">2</span>);
    }
  },
)
</code></pre>
<p>in this way, if the width of the screen is <code>&lt;= kMobileBreakpoint</code> we'll show the CustomGridView widget with a <code>columnRatio</code> of 6 and so on.... but <strong>what does the columnRatio variable mean</strong>? </p>
<p>This is a way I found to make the UI responsive based on the characteristics of the flutter_staggered_grid_view library and the way many web libraries think for defining the number of columns based on the screen size, the widget I used is StaggeredGridView.countBuilder which allows you to define two properties to structure the layout and the number of columns it has, in particular, the two properties have more or less this meaning:</p>
<ul>
<li><strong>crossAxisCount</strong>: the number of columns in the cross axis. If the scroll is from top to bottom, and vice versa (vertical scroll) the cross axis is the horizonal one. The axis in which the scroll movement takes place is called main axis, therefore the perpendicular one is called cross axis;</li>
<li><strong>StaggeredTile.fit(columnRatio)</strong>: number of columns that content can expand to be represented in the layout.</li>
</ul>
<p>By taking advantage of these two properties, the layout can be organized in this way according to the size of the screen</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1623476516814/ATCfGhAXS.jpeg" alt="Columns on GridView" /></p>
<p>Once we have organized the layout of the columns, to simulate a Pinterest card, we just need to create a layout and for simplicity put a random color in the upper part based on a previously set color array</p>
<pre><code class="lang-dart">Container(
  decoration: BoxDecoration(
    color: _myColorList[random.nextInt(_myColorList.length)],
    borderRadius: BorderRadius.circular(<span class="hljs-number">4</span>),
    boxShadow: <span class="hljs-keyword">const</span>[
      BoxShadow(
        color: Colors.black26,
        offset: Offset(<span class="hljs-number">0</span>,<span class="hljs-number">2</span>),
        blurRadius: <span class="hljs-number">6</span>
      )
    ]
  ),
  height: random.nextInt(<span class="hljs-number">75</span>).toDouble() + <span class="hljs-number">200</span>,
  margin: EdgeInsets.symmetric(horizontal: <span class="hljs-number">6</span>, vertical: <span class="hljs-number">6</span>),
  child: Column(children: [
    Expanded(
      child: Container(),
    ),
    Container(
      color: Colors.white,
      child: ListTile(
        leading: FlutterLogo(),
        title: Text(<span class="hljs-string">"Card with index <span class="hljs-subst">$index</span>"</span>),
        subtitle: Text(<span class="hljs-string">"#card #index<span class="hljs-subst">$index</span> #flutter"</span>),
      ),
    )
  ]),
)
</code></pre>
<p>The result is something like this</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1623475542688/3qUbUpct7.png" alt="cardUI.png" /></p>
<h3 id="how-to-improve-it">How to improve it</h3>
<p>You can look inside the code of the flutter_staggered_grid_view library and see other option to experiment with, some hints are:</p>
<ul>
<li>Customize the look and feel of the single card;</li>
<li>Insert an image in the top part of the card, maybe grab it from services like <a target="_blank" href="https://www.pexels.com/">Pexels</a> or <a target="_blank" href="https://unsplash.com/">Unsplash</a>;</li>
<li>Manage device orientation on Android and iOS.</li>
</ul>
<p>You can find the source code in this GitHub repo: <a target="_blank" href="https://github.com/polilluminato/simple-flutter-gridview">simple-flutter-gridview</a>, you can fork, use and modify it as you want, the app uses the latest Flutter 2.2 so it's already with Sound Null Safety, you can build it on Android, iOS and on the Web.</p>
<p>Bye, Alberto</p>
]]></content:encoded></item><item><title><![CDATA[Create a Simple Contact App with Faker & Flutter]]></title><description><![CDATA[This article will show you how to create a simple Flutter App to display a Contact List with fake data with Faker. This article is in the series 
Simple Flutter Apps  where I want to show how to code some simple apps in Flutter to help you get starte...]]></description><link>https://blog.albertobonacina.com/create-a-simple-contact-app-with-faker-and-flutter</link><guid isPermaLink="true">https://blog.albertobonacina.com/create-a-simple-contact-app-with-faker-and-flutter</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Flutter Examples]]></category><category><![CDATA[Flutter SDK]]></category><category><![CDATA[tips]]></category><dc:creator><![CDATA[Alberto Bonacina]]></dc:creator><pubDate>Fri, 04 Jun 2021 05:54:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1622786248883/IvyZSKeyW.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This article will show you how to create a simple <a target="_blank" href="https://flutter.dev/">Flutter</a> App to display a Contact List with fake data with Faker. This article is in the series 
<a target="_blank" href="https://blog.albertobonacina.com/series/simple-flutter-apps">Simple Flutter Apps</a>  where I want to show how to code some simple apps in Flutter to help you get started.</p>
<h3 id="heading-what-we-will-build">What we will build</h3>
<p>We will build a simple Flutter App to show some fake data generated with <a target="_blank" href="https://pub.dev/packages/faker">Faker</a> to simulate a contact list and go into contact details, this is useful to understand some concepts that can be used in Flutter Apps like:</p>
<ul>
<li>generate fake data to test UI design</li>
<li>create a horizontal and vertical scrollview</li>
<li>explore the useful <a target="_blank" href="https://api.flutter.dev/flutter/material/ListTile-class.html">ListTile</a> widget</li>
<li>explore simple navigation between screen</li>
</ul>
<p>The final result will look like this</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Home</td><td>Details</td></tr>
</thead>
<tbody>
<tr>
<td><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1622640036522/8TXEkEUJS.png" alt="App home page" /></td><td><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1622640050619/DaAtPq1Lh.png" alt="App detail page" /></td></tr>
</tbody>
</table>
</div><h3 id="heading-lets-code">Let's code</h3>
<p>You can find all the code in this GitHub repo <a target="_blank" href="https://github.com/polilluminato/simple-flutter-contactlist">simple-flutter-contactlist</a> and these are the main parts:</p>
<ul>
<li><strong>lib/models/contact.dart</strong>: this is the model that represents all the contact details, for the purpose of this post we will use name, surname, phone, email, address, city, username, avatar;</li>
<li><strong>lib/ui/contact_row.dart</strong>: use of ListTile widget where you can create a simple layout with all the components in the right place;</li>
<li><strong>lib/pages/singlecontact_page.dart</strong>: single page to show all the contact information.</li>
</ul>
<p>As we did in the <a target="_blank" href="https://blog.albertobonacina.com/create-a-simple-timetable-app-with-json-and-flutter">previous post</a> we have to create a dart class to represent our Contact</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Contact</span> </span>{
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> name;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> surname;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> phone;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> email;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> address;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> city;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> username;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> avatar;

  Contact(
      {<span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.name,
      <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.surname,
      <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.phone,
      <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.email,
      <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.address,
      <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.city,
      <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.username,
      <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.avatar});
}
</code></pre>
<p>To create all the fake information about a contact we use <a target="_blank" href="https://pub.dev/packages/faker">Faker</a></p>
<pre><code class="lang-dart"><span class="hljs-comment">//import library</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'package:faker/faker.dart'</span>;
<span class="hljs-comment">//initialize it</span>
<span class="hljs-keyword">final</span> _faker = <span class="hljs-keyword">new</span> Faker();

<span class="hljs-comment">//Create single Contact</span>
Contact _thisPerson = Contact(
    name: _contactFirstName,
    surname: _contactLastName,
    phone: _faker.phoneNumber.us(),
    email: Utils.createEmail(
        _contactFirstName, _contactLastName, _domainName),
    address: _faker.address.streetAddress(),
    city: _faker.address.city(),
    username: Utils.createUsername(
        _contactFirstName, _contactLastName),
    avatar: Utils.createAvatarLink(
        _contactFirstName, _contactLastName));
</code></pre>
<p>To maintain consistency between name, surname, email, and username of the random data generated by Faker I created three simple functions that I put in the <code>Utils.dart</code> file </p>
<pre><code class="lang-dart"><span class="hljs-built_in">String</span> createEmail(<span class="hljs-built_in">String</span> firstName, <span class="hljs-built_in">String</span> lastName, <span class="hljs-built_in">String</span> domainname){
  <span class="hljs-keyword">return</span> <span class="hljs-string">"<span class="hljs-subst">${lastName.toLowerCase()}</span>.<span class="hljs-subst">${firstName.toLowerCase()}</span>@<span class="hljs-subst">$domainname</span>"</span>;
}

<span class="hljs-built_in">String</span> createUsername(<span class="hljs-built_in">String</span> firstName, <span class="hljs-built_in">String</span> lastName){
  <span class="hljs-keyword">return</span> <span class="hljs-string">"<span class="hljs-subst">${lastName.toLowerCase()}</span>_<span class="hljs-subst">${firstName.toLowerCase()}</span>"</span>;
}

<span class="hljs-built_in">String</span> createAvatarLink(<span class="hljs-built_in">String</span> firstName, <span class="hljs-built_in">String</span> lastName){
  <span class="hljs-keyword">return</span> <span class="hljs-string">"https://eu.ui-avatars.com/api/?name=<span class="hljs-subst">$firstName</span>+<span class="hljs-subst">$lastName</span>&amp;background=2f855a&amp;color=fff"</span>;
}
</code></pre>
<p>With all the informations on the contact, we can now display it in a single row with the ListTile widget that lets you create a row layout with little effort and arranges information in the right way, the main parts are:</p>
<pre><code class="lang-dart">ListTile(
    <span class="hljs-comment">//Action to perform when the user tap on the row</span>
    onTap: 
    <span class="hljs-comment">//Content to display, in the most case as an icon, on the left</span>
    leading: 
    <span class="hljs-comment">//Main text widget to display in the row</span>
    title: 
    <span class="hljs-comment">//Secondary text widget to display in the row</span>
    subtitle: 
    <span class="hljs-comment">//Content to display, in the most case as an icon, on the right</span>
    trailing: 
);
</code></pre>
<p>two examples of ListTile widget in the app are</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1622784394848/fzaXxZQqu.png" alt="ListTile first example" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1622784403269/_cHPZSzBQ.png" alt="ListTile second example" /></p>
<p>To perform the navigation between screen I used the <a target="_blank" href="https://api.flutter.dev/flutter/widgets/Navigator-class.html">Navigator</a> widget to go to and from screens</p>
<pre><code class="lang-dart"><span class="hljs-comment">//In this way I can go into another screen</span>
Navigator.push(
  context,
  MaterialPageRoute(
    builder: (context) =&gt; SingleContactPage(
      contact: <span class="hljs-keyword">this</span>.contact,
    ),
  ),
);

<span class="hljs-comment">//In this way I can go back to the previous screen</span>
Navigator.pop(context);
</code></pre>
<h3 id="heading-how-to-improve-it">How to improve it</h3>
<p>There are lots of improvements that we can do to make our app better, now I can list some of them to give you some inspirations:</p>
<ul>
<li>let the user perform a call by tapping on the phone icon in the list of contacts, the <a target="_blank" href="https://pub.dev/packages/url_launcher">url_launcher</a> package can make it happens;</li>
<li>let the user filter on the contacts list; </li>
<li>test more layout variation on the ListTile Widget both in the contacts list as well in the detail page;</li>
<li>define a custom layout for the detail page, on sites like <a target="_blank" href="https://www.uplabs.com/">Uplabs</a>, <a target="_blank" href="https://www.behance.net/">Behance</a> or <a target="_blank" href="https://www.pinterest.com">Pinterest</a> you could find lots of UI Design to improve it.</li>
</ul>
<p>You can find all the app code in this GitHub repo: <a target="_blank" href="https://github.com/polilluminato/simple-flutter-contactlist">simple-flutter-contactlist</a>, you can fork, use and modify it as you want, the app uses the latest Flutter 2.2 so it's already with Sound Null Safety, you can build it on Android, iOS and on the Web.</p>
<p>Bye, Alberto</p>
]]></content:encoded></item><item><title><![CDATA[Create a Simple Timetable App with JSON & Flutter]]></title><description><![CDATA[This article will show you how to create a simple Flutter App to display a list of appointments from a JSON file. This is the first article in the series 
Simple Flutter Apps  where I want to show how to code some simple apps in Flutter to help you g...]]></description><link>https://blog.albertobonacina.com/create-a-simple-timetable-app-with-json-and-flutter</link><guid isPermaLink="true">https://blog.albertobonacina.com/create-a-simple-timetable-app-with-json-and-flutter</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Flutter Examples]]></category><category><![CDATA[Flutter SDK]]></category><category><![CDATA[Programming Tips]]></category><dc:creator><![CDATA[Alberto Bonacina]]></dc:creator><pubDate>Wed, 26 May 2021 04:53:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1622004625857/4Ls_AtYVW.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This article will show you how to create a simple <a target="_blank" href="https://flutter.dev/">Flutter</a> App to display a list of appointments from a JSON file. This is the first article in the series 
<a target="_blank" href="https://blog.albertobonacina.com/series/simple-flutter-apps">Simple Flutter Apps</a>  where I want to show how to code some simple apps in Flutter to help you get started.</p>
<h3 id="what-we-will-build">What we will build</h3>
<p>We will build a simple Flutter App to read a list of appointments from a local JSON file and show them in a list, this is useful to understand some concepts that can be used in Flutter Apps like:</p>
<ul>
<li>read a file from the local storage</li>
<li>parse JSON file</li>
<li>model a JSON file to a list of Dart Classes</li>
<li>create a list with a FutureBuilder</li>
</ul>
<p>The final result will look like this</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1622003704005/yec6MqFfb.png" alt="home_page.png" /></p>
<h3 id="lets-code">Let's code</h3>
<p>You can find all the code in this GitHub repo <a target="_blank" href="https://github.com/polilluminato/simple-flutter-timetable">simple-flutter-timetable</a> and these are the main parts:</p>
<ul>
<li><strong>assets/json/timetable.json</strong>: file json with the timetable that represent our "store", image that as our DB or API result;</li>
<li><strong>lib/model/appointment.dart</strong>: this is the model that allows us to convert the JSON object into a Dart class;</li>
<li><strong>lib/pages/home_page.dart</strong>: main screen of the app with all the calls to read and parse the JSON;</li>
<li><strong>lib/ui/appointment.list.dart</strong>: listview to read the List of Classes from JSON and display it on screen;</li>
</ul>
<p>In this post I will only explain the most important parts because if you follow the code in the repo it's pretty easy to understand what it does. </p>
<p>First of all you have to tell Flutter that It can use the <em>timetable.json</em> file and to do that you have to put those lines in the pubspec.yaml file</p>
<pre><code class="lang-yaml">  <span class="hljs-attr">assets:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">assets/json/timetable.json</span>
</code></pre>
<p>After that we have to provide a Dart class that represents the information, in our case I create the appointment with this data</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"day"</span>: <span class="hljs-string">"2021-05-24"</span>,
    <span class="hljs-attr">"time"</span>: <span class="hljs-string">"09:00 -&gt; 11:00"</span>,
    <span class="hljs-attr">"type"</span>: <span class="hljs-string">"relax"</span>,
    <span class="hljs-attr">"title"</span>: <span class="hljs-string">"Yoga class"</span>
}
</code></pre>
<p>and the Dart class is this one</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Appointment</span> </span>{
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> day;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> time;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> type;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> title;

  Appointment({<span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.day, 
      <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.time, 
      <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.type, 
      <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.title});

  <span class="hljs-comment">//This is the function that lets you to convert the </span>
  <span class="hljs-comment">//  JSON representation of the Appointment in its Dart class</span>
  <span class="hljs-keyword">factory</span> Appointment.fromJson(<span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">dynamic</span>&gt; json) {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Appointment(
      day: json[<span class="hljs-string">'day'</span>] <span class="hljs-keyword">as</span> <span class="hljs-built_in">String</span>,
      time: json[<span class="hljs-string">'time'</span>] <span class="hljs-keyword">as</span> <span class="hljs-built_in">String</span>,
      type: json[<span class="hljs-string">'type'</span>] <span class="hljs-keyword">as</span> <span class="hljs-built_in">String</span>,
      title: json[<span class="hljs-string">'title'</span>] <span class="hljs-keyword">as</span> <span class="hljs-built_in">String</span>
    );
  }
}
</code></pre>
<p>We can read the file and parse the content with these two functions in the <em>home_page.dart</em></p>
<pre><code class="lang-dart">Future&lt;<span class="hljs-built_in">String</span>&gt; getJsonStringFromFile() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> DefaultAssetBundle.of(context)
              .loadString(<span class="hljs-string">'assets/json/timetable.json'</span>);
}

<span class="hljs-built_in">List</span>&lt;Appointment&gt; parseJson(<span class="hljs-built_in">String</span> response) {
  <span class="hljs-keyword">final</span> parsed =
      json.decode(response.toString()).cast&lt;<span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">dynamic</span>&gt;&gt;();
  <span class="hljs-keyword">return</span> parsed.map&lt;Appointment&gt;((json) =&gt; <span class="hljs-keyword">new</span> Appointment.fromJson(json)).toList();
}
</code></pre>
<p>Note in this case that the function <strong>getJsonStringFromFile</strong> has been declared <strong>async</strong> since accessing the memory is an operation that can take some time and therefore the reading of the file is something that will happen in the "near future". To take advantage of the async code and not to "freeze" the UI, a FutureBuilder has also been added, a very useful widget when you need to show a portion of the UI in which data comes from an async, in this way it is possible to provide a placeholder widget while the data arrives, once the data has arrived it is then possible to design the definitive UI</p>
<pre><code class="lang-dart"><span class="hljs-keyword">new</span> FutureBuilder(
  future: getJsonStringFromFile(),
  builder: (context, snapshot) {
    <span class="hljs-keyword">if</span> (!snapshot.hasData) {
      <span class="hljs-comment">//Placeholder widget because the data hasn't arrived yet</span>
      <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Center(
        child: <span class="hljs-keyword">new</span> CircularProgressIndicator(),
      );
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-built_in">List</span>&lt;Appointment&gt; appointments = parseJson(snapshot.data.toString());
      <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> AppointmentList(
        appointments: appointments,
      );
    }
  },
),
</code></pre>
<p>To customize the UI, the <em>type</em> field in the class was used to show a custom icon in a single row and allow the user to easily distinguish the different types of appointments.</p>
<h3 id="how-to-improve-it">How to improve it</h3>
<p>There are lots of improvements that we can do to make our app better, now I can list some of them to give you some inspirations:</p>
<ul>
<li>Read JSON file from a custom URL on the internet: in this way you are not limited to the JSON that you have in your local storage, so if you have to update the JSON file you don't have to update the app, but you only have to update the JSON file because the app will read the updated one;</li>
<li>Add more information on the single appointment like the location, split start and end time, insert a description or some notes on the appointment;</li>
<li>Create a detail page of the appointment to show all the information;</li>
<li>Allow the user to filter the contents of the list: for example you can add filters by type of appointment or by date, in case of a very long list of appointments it can be very convenient;</li>
<li>Customize more the look and feel of the single row, on sites like <a target="_blank" href="https://www.uplabs.com/">Uplabs</a>, <a target="_blank" href="https://www.behance.net/">Behance</a> or <a target="_blank" href="https://www.pinterest.com">Pinterest</a> you could find lots of UI Design to improve it.</li>
</ul>
<p>You can find all the app code in this GitHub repo: <a target="_blank" href="https://github.com/polilluminato/simple-flutter-timetable">simple-flutter-timetable</a>, you can fork, use and modify it as you want, the app uses the latest Flutter 2.2 so it's already with Sound Null Safety, you can build it on Android, iOS and on the Web.</p>
<p>Bye, Alberto</p>
]]></content:encoded></item><item><title><![CDATA[How to protect yourself online in 5 steps]]></title><description><![CDATA[In this last year where all of us for obvious necessities have moved to a much more online life for study, work or leisure and therefore we use the net more to surf, inform ourselves, watch TV series or movies, I thought it was useful to remember som...]]></description><link>https://blog.albertobonacina.com/how-to-protect-yourself-online-in-5-steps</link><guid isPermaLink="true">https://blog.albertobonacina.com/how-to-protect-yourself-online-in-5-steps</guid><category><![CDATA[tips]]></category><category><![CDATA[web]]></category><category><![CDATA[privacy]]></category><category><![CDATA[Security]]></category><category><![CDATA[General Advice]]></category><dc:creator><![CDATA[Alberto Bonacina]]></dc:creator><pubDate>Fri, 14 May 2021 05:21:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1620969299517/iBtTAuJnX.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this last year where all of us for obvious necessities have moved to a much more online life for study, work or leisure and therefore we use the net more to surf, inform ourselves, watch TV series or movies, I thought it was useful to remember some basic steps to protect your data so here are 5 very simple steps with which we can increase the protection of our data and put our information a little safer.</p>
<h2 id="do-not-use-the-same-password">Do NOT use the same password</h2>
<p>The first fundamental advice is <strong>not to use the same password</strong> for access and login to the sites to which we are registered because if only one of these credentials were stolen they could be used to access not only the site from which they were taken but also to all others. So do not use your child’s birth date or dog’s name as a password and above all do not use it either to access Facebook, to the bank, or maybe to that online site where you bought something years ago that may not have the same security policies as the most structured sites.</p>
<h2 id="use-a-password-manager">USE a password manager</h2>
<p>It is a good idea <strong>not to use a piece of paper</strong> to mark all the passwords we have and keep them somewhere in the house because we could always lose it but use a password manager (more details <a target="_blank" href="https://blog.albertobonacina.com/i-use-a-password-manager-and-you-should-do-it-too">here</a>) that is a software that allows you to save all the <strong>different passwords</strong> of yours online accounts securely ready to use. Many of these password managers are available as online services to have them always available and allow you to generate complex passwords and auto-fill login forms securely.</p>
<h2 id="always-update-programs-and-the-operating-system">ALWAYS update programs and the operating system</h2>
<p>This is as simple as forgotten by many: <strong>update programs and the operating system</strong> to the latest version available. In this way we will also have all the security updates and bugs will be fixed that could be used against us to steal information from us. This advice applies not only to our PC but also to all mobile devices such as tablets and smartphones, it is strongly recommended to periodically take a ride on the Play Store or the Apple Store to update our apps.</p>
<h2 id="pay-attention-to-how-much-information-you-post-online-and-with-whom-you-share-it">Pay ATTENTION to how much information you post online and with whom you share it</h2>
<p>Post as little information online as it could be used against you by exploiting what is called <a target="_blank" href="https://en.wikipedia.org/wiki/Social_engineering_(security">Social engineering</a>), through which the behavior of a person is studied to obtain useful information that can be exploited to cheat. Here is an example: do you know that purchase you posted on Facebook and are awaiting delivery? An attacker could use this information and pretend to be the company that sold it to you saying that there were problems with the payment and that you have to redo it using a special link that will send you by email but not having access to this information will tell you to give it back on the phone... where is the problem? If you take the bait you just let him know your email (and as mentioned before it might not be difficult to guess the password), in case you went further by clicking on the link that sends you and try to make the payment you will have a nice cloned credit card.</p>
<h2 id="use-two-factor-authentication">USE two-factor authentication</h2>
<p>This is perhaps the most advanced method of all but it is the one that takes security to another level. Two-factor authentication is the ability to enable access and log in with SMS/notification/code that is sent to your mobile phone to confirm your identity and that you must enter to log in, often used to access sites and home banking apps. Why is this method so important? If they were to steal your credentials they could not use them to log in because they would not have the code that arrived on the phone... Not to mention the fact that if that happens, you’ll see right away that something’s wrong.</p>
<h2 id="bonus-use-passphrases-instead-of-passwords">BONUS: use passphrases instead of passwords</h2>
<p>A good way to make your password secure is to <strong>replace it with a passphrase</strong> that is a phrase, duly modified, that is: easy to remember for you, sufficiently long and complex to make vain the efforts to discover it. Here’s an example: consider the phrase</p>
<blockquote>
<p>da Londra a Parigi ci sono circa 450 km</p>
</blockquote>
<p>and convert it into</p>
<blockquote>
<p>fromL0nD0ntoP@risth3r3are@b0ut450km</p>
</blockquote>
<p>Do you know how long it takes to <a target="_blank" href="https://howsecureismypassword.net/">discover it</a>? 8 Hundred Quattuordecillion Years. </p>
<p>Bye, Alberto</p>
]]></content:encoded></item><item><title><![CDATA[Cryptocurrency 101: all you need to know to start]]></title><description><![CDATA[Hi everyone in recent months, interest in crypto has grown, accomplices to some tweet of Musk and NFTs, who have pushed many to approach this world. I have always been fascinated by this world that in some ways I consider the future of finance, I hav...]]></description><link>https://blog.albertobonacina.com/cryptocurrency-101-all-you-need-to-know-to-start</link><guid isPermaLink="true">https://blog.albertobonacina.com/cryptocurrency-101-all-you-need-to-know-to-start</guid><category><![CDATA[Cryptocurrency]]></category><category><![CDATA[crypto]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Alberto Bonacina]]></dc:creator><pubDate>Thu, 22 Apr 2021 11:42:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1618750157461/-G_IriAfYd.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hi everyone in recent months, interest in crypto has grown, accomplices to some tweet of Musk and NFTs, who have pushed many to approach this world. I have always been fascinated by this world that in some ways I consider the future of finance, I have deepened it over time and I wanted to share here a list of essential terms to start on the right foot. The terms are in alphabetical order and not of importance, to facilitate the search.</p>
<h3 id="heading-51-attack">51% Attack</h3>
<p>It is a hypothetical scenario that could occur when 51% of the nodes of a blockchain are under the control of a single entity. In this case, the network consensus would not be distributed enough, because there would be a majority, and the blockchain could be manipulated. The aforementioned entity could arbitrarily block, reverse or duplicate transactions by invalidating the blockchain itself. This attack is as difficult as the blockchain grows in several nodes, values, and usage.</p>
<h3 id="heading-address">Address</h3>
<p>An address in a blockchain is a unique string made up of letters and numbers that identify an account within the blockchain itself. During a transaction, digital assets, often called tokens, are moved between two addresses of the same blockchain.</p>
<h3 id="heading-altcoin">Altcoin</h3>
<p>Altcoins, or "alternative coins", are all cryptocurrencies that were launched after Bitcoin, some examples are for example ETH, LTC, XRP.</p>
<h3 id="heading-annual-percentage-rate-apr">Annual Percentage Rate (APR)</h3>
<p>An annual percentage rate (APR) on a loan is the amount of interest a borrower has to pay on the loan he has taken out. APR is expressed as an annual percentage of the outstanding loan balance and represents the annual cost of the loan.</p>
<h3 id="heading-annual-percentage-yield-apy">Annual Percentage Yield (APY)</h3>
<p>The annual percentage yield (APY) refers to the rate of return earned on a deposit in a year, therefore it translates into the sum that is earned by a person who has deposited funds and left to mature for one year. APY takes into account compound interest, which is calculated periodically and added to the balance.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619074147085/-nivWhcDvb.jpeg" alt="crypto-bitcoin.jpg" /></p>
<h3 id="heading-bitcoin-and-btc">Bitcoin &amp; BTC</h3>
<p>Bitcoin is the first and best-known blockchain worldwide and has its own native cryptocurrency (bitcoin). It is, historically, the first blockchain with associated cryptocurrency, and has always been a dominant presence within the cryptocurrency ecosystem. Bitcoin was founded in 2009, by Satoshi Nakamoto, and is based on the Proof of Work algorithm, a technology for reaching consensus on a decentralized network.</p>
<p>Bitcoin (BTC) is a cryptocurrency that can be transmitted between accounts on the Bitcoin blockchain by exchanging assets between two addresses. </p>
<p>The difference between Bitcoin as a blockchain and bitcoin as a cryptocurrency is in the initial B which in the first case is capitalized, in the second it is lowercase.</p>
<h3 id="heading-block">Block</h3>
<p>Within a blockchain, a block is a single entity that makes up a piece of the chain. Inside, all the information on the transactions carried out (the exchange of tokens/coins between addresses of the blockchain) during a predefined time interval depends on the blockchain itself. The blocks are hung one after the other at the end of the chain, which represents the public ledger known as the blockchain.</p>
<p>A Bitcoin block contains information on the date, time, and amount of transactions, including all information about the addresses involved and the amount of currency they exchanged. The blocks must all be confirmed by the nodes of the network through a process of consent, once the block is confirmed it is added to the end of the chain and the chain can move on to the creation of the next one.</p>
<h3 id="heading-blockchain">Blockchain</h3>
<p>A blockchain is a public register of transactions that is maintained and verified by a decentralized network of peer-to-peer nodes/computers which, thanks to a consensus mechanism, confirms the data.</p>
<p>A sufficiently decentralized blockchain makes it possible to exchange cryptocurrencies to carry out transactions in a secure, verifiable, and rapid way, without authority or centralized intermediaries globally.</p>
<p>Each computer on the network keeps a copy of the entire ledger, making it virtually impossible for a single node to alter past transactions or overwhelm the network.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619091394795/1-PY7qBJw.png" alt="blockchain-crypto.png" /></p>
<h3 id="heading-block-explorer">Block Explorer</h3>
<p>A block explorer is a software that allows users to access all the operating information of a blockchain in real-time: transactions, blocks, addresses, nodes, and balances. Many of these interfaces are available via web browsers, are free, open source, and essential for providing transparency and democratized access to the blockchain network.</p>
<h3 id="heading-cold-wallet">Cold Wallet</h3>
<p>A Cold Wallet is a cryptocurrency wallet that is not connected to the Internet, very often they come in the form of physical devices that store private keys and are used to "keep your cryptocurrencies safe". Very similar by analogy to hard drives for backups not directly connected to a PC or network.</p>
<h3 id="heading-collateral">Collateral</h3>
<p>Collateral refers to an asset that is offered as collateral for the repayment of a loan. In the event that an individual is unable to repay the borrowed principal, the collateral will be held by the lender.</p>
<p>When borrowing money on a lending platform, collateral is often expressed in the form of tokens which are blocked by the platform itself. The guarantee is returned when the loan is repaid. If the loan is not repaid, the guarantee remains blocked on the platform and is no longer available to the loan applicant.</p>
<h3 id="heading-cryptocurrency">Cryptocurrency</h3>
<p>Cryptocurrency is a digital asset that can be exchanged between two parties and that uses the internet for its circulation. Cryptocurrencies use blockchain as a distributed ledger of transactions that has inherent characteristics of transparency and advanced cryptography.
The exchange of these assets or cryptocurrencies through the blockchain allows the certainty that they cannot be spent twice even in the absence of a centralized intermediary. The first cryptocurrency to achieve mainstream success was bitcoin followed in the following years by many other cryptocurrencies, often called altcoins.</p>
<h3 id="heading-cryptocurrency-exchange">Cryptocurrency Exchange</h3>
<p>Cryptocurrency exchanges are similar to traditional exchanges where digital assets can be bought, sold, and exchanged for fiat currency (Dollar, Euro, Pound, etc...) or other digital assets, for example, they make direct exchange between two different cryptocurrencies possible.</p>
<p>Compared to the early years, when transactions were often unregulated, exchanges have evolved greatly to ensure transparency, accessibility, and legal compliance in the countries in which they operate. To compete in user numbers and trading volume they offer competitive trading fees, exchange rates, and user-friendly features.</p>
<h3 id="heading-cryptomining">Cryptomining</h3>
<p>Cryptocurrency mining is the process by which, through solving complex equations, a blockchain with the Proof-of-Work consensus mechanism verifies transactions and adds new blocks to the blockchain. The computers that perform these mathematical operations are called nodes and the process by which they solve equations is called mining. For their efforts, the owners of these nodes, also called miners, are rewarded with a fraction of the blockchain's native cryptocurrency.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619074507755/fRC1jtaH1.jpeg" alt="bitcoin-crypto-mining-farm.jpg" /></p>
<h3 id="heading-decentralized-applications-dapps">Decentralized Applications (dApps)</h3>
<p>Decentralized applications -dApps- leverage the blockchain to offer services ranging from investments to loans, games, and governance. From a graphic point of view, they are very similar to web applications but the back-end processes do not use centralized servers to carry out transactions but implement them in a distributed and peer-to-peer way, often interacting with automated smart contracts on networks such as Ethereum.</p>
<h3 id="heading-decentralized-finance-defi">Decentralized Finance (DeFi)</h3>
<p>Decentralized Finance (DeFi) is a very growing sector in the blockchain landscape, offering financial services and technologies based on Ethereum. DeFi exchanges, loans, investments, and tokens are much more transparent, do not need centralized authorization, and are interoperable compared to traditional financial services, governance is decentralized and promotes fair stakeholder ownership.</p>
<h3 id="heading-erc-20">ERC-20</h3>
<p>The ERC-20 standard represents the set of technical specifications that an Ethereum token (often a cryptocurrency) must have to be fully compatible with the Ethereum blockchain. Through this standard, tokenized assets, tokens, or contracts can be created that can be bought, sold, and traded together with cryptocurrencies such as bitcoin (BTC) and ether (ETH) and used interoperably between Ethereum-based dApps.</p>
<h3 id="heading-ethereum-and-eth">Ethereum &amp; ETH</h3>
<p>Ethereum was launched in 2015 as a decentralized global network based on its own blockchain that forms the basis of an ecosystem of decentralized applications (dApps) that leverage tokens and automated smart contracts.</p>
<p>The blockchain's native token called Ether (ETH) is used to power the network. Ether plays a vital role in the Ethereum ecosystem, where transactions are paid for through micro-payments of ETH called gas.</p>
<p>All contracts on the Ethereum network are intelligent and self-executing, this means that there is no need for a central authority or an intermediary to control its operation. Ethereum, which by its nature is open-source, programmable, private, and resistant to censorship, forms the backbone of a decentralized Internet, where there are already many innovations such as Initial Coin Offerings (ICOs), Stablecoins, and decentralized finance applications.</p>
<h3 id="heading-fiat-currency">Fiat Currency</h3>
<p>A fiat currency is a government-issued currency of a state that is used by its citizens as a bargaining chip to buy goods and services within their nation. Most modern national or multi-country currencies, such as the Dollar or Euro, are fiat currencies.</p>
<p>Their face value is defined by the government or entity that issued it, they are not backed by a physical commodity (such as gold and silver) and to operate properly they must be durable, wearable, uniform, and limited.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619091526738/x7mAF3KVW.jpeg" alt="fiat-currency-crypto.jpg" /></p>
<h3 id="heading-fork">Fork</h3>
<p>A fork occurs when a blockchain splits into two branches or two different blockchains when an update occurs in the blockchain management protocol in which not all nodes decide to adapt to the update. The fork can be "soft" or "hard", in the first case the update is backward compatible with previous versions of the blockchain, the updated and non-updated nodes can still operate with each other, in the case of a "hard" fork this what cannot happen and the two blockchains become two distinct entities with a life of their own.</p>
<h3 id="heading-gas">Gas</h3>
<p>Gas refers to the fees associated with transactions and the execution of contracts on the Ethereum blockchain. Decentralized applications (dApps) take advantage of smart contracts in which rules are defined for the events' execution. These events are associated with transactions that have costs based on the actions they contain, the computing power, and the time required for their execution.</p>
<p>The gas is used to allocate the resources of the miners' network that support the blockchain, it is also used for spam mitigation because it discourages malicious actors who could send many small transactions to clog the network, having a price to pay to be able to do them, they are discouraged from doing so.</p>
<h3 id="heading-halving">Halving</h3>
<p>When the reward given to miners on a blockchain is reduced by 50%, a halving is said to have occurred. These halving events occur at fixed intervals and their scheduling is defined within the protocol of the blockchain itself. In the case of Bitcoin, halving occurs every 210,000 blocks generated, approximately every 4 years.</p>
<h3 id="heading-hash-rate">Hash Rate</h3>
<p>Within a blockchain with a Proof-of-Work consensus mechanism, the hash rate identifies the unit of measurement of the computing power of a single node, generally, it is evaluated in terahash per second (TH/s) or its submultiples, as miners increase or decrease within the network the hash rate changes accordingly.</p>
<h3 id="heading-hodl">HODL</h3>
<p>"Hodl" is a slang term that refers to keeping cryptocurrencies in a wallet as opposed to selling. Everything was born from an error of a user on Bitcointalk who wrongly wrote the word "hold", which was later transformed into a meme by the community.</p>
<h3 id="heading-initial-coin-offering-ico">Initial Coin Offering (ICO)</h3>
<p>Sometimes to finance a new blockchain project, a decentralized application (dApps), or digital assets, Initial Coin Offers or tokens are launched to raise funds, made possible by the Ethereum blockchain. These sales are called ICOs and the ownership of these tokens allows the user to have an economic return or benefit in the project. In fact, this mechanism is very similar to the purchase of shares of a company but it is all managed in a decentralized way on the Ethereum blockchain.</p>
<h3 id="heading-liquidity-pool">Liquidity Pool</h3>
<p>A liquidity pool is crowdsourcing of cryptocurrencies that have been locked into a contract used to facilitate and speed up the exchange of assets or coins on a decentralized exchange.</p>
<h3 id="heading-market-capitalization">Market Capitalization</h3>
<p>Market capitalization is the total value of all tokens of a cryptocurrency. This value is obtained by multiplying the total number of coins or tokens in circulation by the unit value of a single token in a fiat currency, for example, to date, the market capitalization of BTC is approximately 1,021,263,394,654 USD.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619074658008/Onxvz1VCN.png" alt="crypto-marketcap.png" /></p>
<h3 id="heading-miner">Miner</h3>
<p>Miners are an essential component of all blockchains based on the Proof-of-Work (PoW) consensus protocol, they are responsible for validating the transactions carried out and registering them in a new block. To validate the transactions they have to solve complex mathematical problems, their resolution leads to the creation of new tokens, simultaneously increasing the security and reliability of the network. To incentivize users to provide computing power to perform these complex computations, miners are rewarded with a fraction of the blockchain's native currency with each new block created.</p>
<h3 id="heading-mining-and-mining-pool">Mining and Mining Pool</h3>
<p>Mining is the process whereby a computer, or generically a node, provides its computing power to the blockchain so that transactions are validated and new blocks can be produced in all those blockchains that use Proof-of-Work (PoW). During the mining process the miners, node managers, are rewarded with the native coin or token of the blockchain.</p>
<p>To increase the chances of mining a block of transactions, miners merge into what is called a mining pool to combine individual computing power. In the case of extraction of a block, the reward is divided proportionally on the basis of the participation of each.</p>
<h3 id="heading-non-fungible-token-nft">Non-Fungible Token (NFT)</h3>
<p>A non-fungible token (NFT) is a special type of token that represents a unique digital asset that cannot be exchanged for another type of digital asset or split into smaller pieces. This feature makes it different from other types of tokens or cryptocurrencies on the Bitcoin or Ethereum blockchains which are fungible.</p>
<h3 id="heading-proof-of-stake">Proof of Stake</h3>
<p>The Proof of Stake (PoS) consensus mechanism is one of the most widely used mechanisms today for validating transactions on a blockchain that differs from Proof-of-Work.</p>
<p>In the Proof of Stake, nodes participate democratically in the validation of transactions as the participants point to the native tokens of the network and randomly, in proportion to the number of tokens staked, they are chosen to validate the data of the block, thus generating the next block and earning native tokens as a reward.</p>
<p>Such a network offers greater security, resilience, and computing power, and also allows the creation of decentralized governance of the platform by voting on updates and decisions. PoS networks are proving to be faster and more scalable than blockchains and more energy efficient.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619091630613/xl2c4ytAs.jpeg" alt="pow-vs-pos.jpg" /></p>
<h3 id="heading-proof-of-work">Proof of Work</h3>
<p>Proof of Work (PoW) is a consensus mechanism first brought to the fore by the Bitcoin blockchain. This type of mechanism relies on the concept of mining to maintain the network. The miners provide their own computing power that is required to solve complex mathematical problems, these calculations are necessary for the confirmation of the data present in the transactions, as a reward in the case of a correct solution, miners are rewarded with the cryptographic token underlying the network.</p>
<p>Proof-of-Work systems are decentralized, require a high amount of power to operate, and typically poorly scalable for widespread adoption by the general public.</p>
<h3 id="heading-satoshi-nakamoto">Satoshi Nakamoto</h3>
<p>Satoshi Nakamoto is the individual or pseudonym of the group responsible for creating the Bitcoin protocol. Nakamoto released the Bitcoin white paper in October 2008 and mined the first block on the Bitcoin network in January 2009.</p>
<p>About him, or them, nothing has been known since April 2011 when he posted a message on an online forum in which he said he "moved on to other things". Satoshi Nakamoto's identity is still surrounded by an aura of mystery and several unconfirmed theories claim to have revealed his identity.</p>
<h3 id="heading-stablecoin">Stablecoin</h3>
<p>A stablecoin is a digital currency created for the sole purpose of maintaining a stable value over time and not being affected by the volatility of the cryptocurrency market. Most stablecoins tie their value to a predetermined fiat currency, having no significant fluctuations they are designed to be used rather than as an investment.</p>
<h3 id="heading-staking">Staking</h3>
<p>Staking is the process by which a user "bets" or blocks their cryptocurrency tokens in a network by participating in the consensus mechanism, thus ensuring the security and functionality of the blockchain. In order to encourage staking by users on a blockchain, most projects reward users with annualized financial returns.</p>
<h3 id="heading-token">Token</h3>
<p>When we talk about tokens in a blockchain we refer to the unit of value for an asset that is managed by a smart contract and an underlying distributed ledger. These tokens, which can be fungible or non-fungible, are used to store value in a blockchain which is very often Ethereum. Initially, these tokens were used to manage simple transactions but in recent times more and more complex tokens are being designed that manage much more variable use cases for example for network governance and maintenance.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619091198018/GIpwZDB9y.jpeg" alt="crypto-wallet.jpg" /></p>
<h3 id="heading-wallet">Wallet</h3>
<p>A cryptocurrency wallet is a physical device (hardware), program, or online service that saves users' public and private keys, this allows them to perform transactions on various blockchains for the exchange, purchase, or sale of cryptographic assets. The wallet may or may not be connected to the internet, in this case, we are talking about a hot or cold wallet, it may or may not be guarded if it is guarded a trusted third party has control of a user's keys if it is not guarded only the user has his own private keys.</p>
<h3 id="heading-whitepaper">Whitepaper</h3>
<p>A white paper is a technical document that is written by those who carry out a blockchain project or by a service that uses one, which describes the operating methodologies, the structure of the project, governance, the technology used, future developments, etc... It is often published in the early stages when looking for financiers to invest in the project and can subsequently be updated in case of progress or changes.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, we have listed and described a series of basic terms necessary to properly approach the world of cryptocurrencies. There are many other interesting concepts to discover once you enter this world, but to take the first steps I think these are more than enough.</p>
<p>Bye, Alberto</p>
]]></content:encoded></item><item><title><![CDATA[Flutter & Brave: test your Web Apps on your favorite browser]]></title><description><![CDATA[Hi everyone in my last series on Flutter I show you all the announcements made by the Flutter team and now I want to show you how you can use Brave as a browser to test your Flutter Apps on the Web.
Problem & Solution
To test your Flutter apps on the...]]></description><link>https://blog.albertobonacina.com/flutter-and-brave-test-your-web-apps-on-your-favorite-browser</link><guid isPermaLink="true">https://blog.albertobonacina.com/flutter-and-brave-test-your-web-apps-on-your-favorite-browser</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Browsers]]></category><category><![CDATA[Programming Tips]]></category><dc:creator><![CDATA[Alberto Bonacina]]></dc:creator><pubDate>Mon, 12 Apr 2021 21:31:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1618262873638/4rmSQpFbk.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hi everyone in my last <a target="_blank" href="https://blog.albertobonacina.com/series/flutter-engage-2021">series on Flutter</a> I show you all the announcements made by the Flutter team and now I want to show you how you can use Brave as a browser to test your Flutter Apps on the Web.</p>
<h2 id="problem-and-solution">Problem &amp; Solution</h2>
<p>To test your Flutter apps on the web you need a Chrome executable as said by <code>flutter doctor</code> command: </p>
<pre><code class="lang-bash">user@localhost:~$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.0.4, on Linux, locale it_IT.UTF-8)
[✗] Chrome - develop <span class="hljs-keyword">for</span> the web (Cannot find Chrome executable at google-chrome)
    ! Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable. 
...
</code></pre>
<p>and based on the <a target="_blank" href="https://flutter.dev/docs/development/platform-integration/web#which-web-browsers-are-supported-by-flutter">documentation</a>, Chrome and Edge are supported as the default browsers for debugging your app, but our loved <a target="_blank" href="https://brave.com/">Brave Browser</a> is based on <a target="_blank" href="https://en.wikipedia.org/wiki/Chromium_(web_browser)">Chromium</a> so you can export the CHROME_EXECUTABLE variable to your Brave installation and use it. All you have to do, based on your Linux operating system (for Windows and macOS the process is similar), is to modify your <code>.bashrc</code> file and insert this line:</p>
<pre><code class="lang-bash"><span class="hljs-comment">#Put your Brave installation location here</span>
<span class="hljs-built_in">export</span> CHROME_EXECUTABLE=<span class="hljs-string">"/opt/brave.com/brave/brave-browser"</span>
</code></pre>
<p>Now if you save the file, close the terminal, reopen it, run again <code>flutter doctor</code> you should see:</p>
<pre><code class="lang-bash">user@localhost:~$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.0.4, on Linux, locale it_IT.UTF-8)
[✓] Chrome - develop <span class="hljs-keyword">for</span> the web
...
</code></pre>
<p>So now if you run your Flutter Web project you'll use Brave as the browser to debug it 🚀. I personally use Brave to test a new web app that I'm developing as a side project and all works well.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618205376632/1TSusJw3t.png" alt="flutter-web-brave-browser.png" /></p>
<p>Bye, Alberto</p>
]]></content:encoded></item><item><title><![CDATA[Flutter Web & Desktop: two platforms, endless possibilities]]></title><description><![CDATA[With this article, we close the series dedicated to Flutter Engage 2021 by dedicating ourselves to the two new platforms that were introduced with the release of Flutter 2.0: Web and Desktop. The support is official and production-ready (under early ...]]></description><link>https://blog.albertobonacina.com/flutter-web-and-desktop-two-platforms-endless-possibilities</link><guid isPermaLink="true">https://blog.albertobonacina.com/flutter-web-and-desktop-two-platforms-endless-possibilities</guid><category><![CDATA[Flutter]]></category><category><![CDATA[events]]></category><category><![CDATA[Flutter SDK]]></category><dc:creator><![CDATA[Alberto Bonacina]]></dc:creator><pubDate>Wed, 31 Mar 2021 05:26:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1616938639289/hK_ptXhV7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>With this article, we close the series dedicated to <a target="_blank" href="https://blog.albertobonacina.com/series/flutter-engage-2021">Flutter Engage 2021</a> by dedicating ourselves to the two new platforms that were introduced with the release of <strong>Flutter 2.0</strong>: Web and Desktop. The support is official and production-ready (under early release flag for desktop), this means that it is possible to target both Web and Desktop (macOS, Linux, and Windows) for a production application. In the next paragraphs, we will see what this means and how it introduces in the development of our Flutter applications.</p>
<h2 id="web">Web</h2>
<p>The support for the web goes in Flutter's direction to develop applications that can reach the user whatever the device he's using. The web is everywhere around us, Flutter allows us to write applications that not only have as targets Android and iOS, but the same codebase can be compiled and transformed to run in any web browser.</p>
<p>The emphasis is on the development of web applications and not static sites, in this way you can replicate the same functionality of native applications in the browser. Flutter, therefore, focuses on 3 main use cases:</p>
<ul>
<li><a target="_blank" href="https://web.dev/progressive-web-apps/">Progressive Web Apps</a>  (PWA): real applications that run within the browser, can communicate with the hardware and sensors of the underlying device, can be installed and have customized graphics;</li>
<li><strong>Single Page Application</strong> (SPA): applications that load their content when they are initialized and subsequently communicate with other web services;</li>
<li><strong>Mobile apps</strong>: porting of applications initially developed only for Android and iOS that users can now use in the browser. </li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1616937071394/YgmJYzwqg.png" alt="web-support-flutter.png" /></p>
<p>To get to this point, many changes have been made to the framework to make it performant with the use of <a target="_blank" href="https://skia.org/user/modules/canvaskit">CanvasKit</a> for the part of rendering the widgets with an increase in performance, especially in desktop browsers. Another feature of the web that Flutter supports is <a target="_blank" href="https://flutter.dev/docs/development/ui/navigation/url-strategies">Custom URLs</a>, to ensure that your users can reach your app anywhere with just a click of a URL. </p>
<p>Great attention was also put to all interactions and features of browsers such as scrollbar, the multitude of form factors and resolutions, accessibility functions such as VoiceOver or TalkBack, correct management of keyboard inputs, text selection, and constant support for new features that are made available in modern browsers.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1616938437976/L0ebAKVpZ.png" alt="invoice-ninja-web-mobile.png" /></p>
<p>There are already several applications in production that are developed in Flutter for the web and one of them is <a target="_blank" href="https://www.invoiceninja.org/">InvoiceNinja</a>, which has recently arrived in version 5 and which uses the same codebase for the online and mobile version, <a target="_blank" href="https://edu.irobot.com/what-we-offer/irobot-coding">iRobot Coding App</a> which allows children to approach the world of programming, <a target="_blank" href="https://rive.app/">Rive</a> who offers designers a powerful tool for creating custom animations that can ship to any platform.</p>
<p>The <a target="_blank" href="https://flutter.gskinner.com/">Flutter Folio</a> application was created by <a target="_blank" href="https://gskinner.com/">gskinner</a> which brings a very important showcase on how it is possible to bring the same application on all platforms supported by Flutter: <strong>iOS</strong>, <strong>Android</strong>, <strong>Mac</strong>, <strong>Linux</strong>, <strong>Windows</strong>, and the <strong>Web</strong>. With this application, you can browse all the features of the app from any device you want!</p>
<h2 id="desktop">Desktop</h2>
<p>Desktop support for Flutter is another very interesting announcement because it opens up interesting scenarios by being able to develop applications for macOS, Linux, and Windows as well. In this regard, there are already examples of software written by large companies that target the desktop, let's see them together.</p>
<p>Let's start with <a target="_blank" href="https://canonical.com/">Canonical</a> which in the development of the Linux distribution <a target="_blank" href="https://ubuntu.com/">Ubuntu</a> decided to choose Flutter as the default framework for the development of its next applications. This means a lot for Flutter on the Linux desktop as the collaboration between Canonical and the Flutter team will benefit the entire developer community. The application they decided to start with is nothing less than the <strong>Ubuntu Installer</strong>, and this is a huge decision because the installer is one of the main programs, in fact, one of the first, that the user uses and it is critical that they can deliver rock-solid experiences on a huge variety of hardware configurations.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1617166874387/rSCIqUBol.jpeg" alt="flutter-desktop.jpeg" /></p>
<p><strong>Toyota</strong> also decided to use Flutter for the development of its applications and in particular for the realization of its infotainment systems right into the heart of their vehicles. Toyota chose Flutter because of its <strong>high performance</strong> in a constrained environment, <strong>consistency of experience</strong> including smartphone-tier touch mechanics, <strong>fast iteration</strong> and quicker feedback loop, <strong>developer ergonomics</strong> allows for developers to make use of all the multi-platform tools.</p>
<h2 id="conclusions">Conclusions</h2>
<p>The support for the desktop and all the other innovations announced by the Flutter Team in this new 2.0 release lead the framework in the direction it has always given: <strong>beautiful native apps in record time</strong>. And we have seen that this native is expanding more and more allowing now to create applications that target 6 different platforms. The future is going to be very interesting for Flutter and I can't wait to see where he can go.</p>
<p>Bye, Alberto.</p>
<h3 id="links">Links</h3>
<ul>
<li><a target="_blank" href="https://medium.com/googleplaydev/seamless-multi-platform-app-development-with-flutter-ea0e8003b0f9">Seamless multi-platform app development with Flutter</a></li>
<li><a target="_blank" href="https://medium.com/flutter/flutter-web-support-hits-the-stable-milestone-d6b84e83b425">Flutter web support hits the stable milestone</a></li>
<li><a target="_blank" href="https://flutter.dev/web">Web support for Flutter</a></li>
<li><a target="_blank" href="https://hillel.dev/2021/03/17/adapting-our-flutter-mobile-app-to-web-and-desktop/">Adapting our Flutter mobile app to web and desktop</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Become a better designer by developing Flutter Apps]]></title><description><![CDATA[In this article, I want to deepen a talk related to Flutter Engage held by @filiphracek, where he presents some ideas for developing beautiful Flutter applications.
We all know that the concept of beauty is subjective, but some tricks can be used to ...]]></description><link>https://blog.albertobonacina.com/become-a-better-designer-by-developing-flutter-apps</link><guid isPermaLink="true">https://blog.albertobonacina.com/become-a-better-designer-by-developing-flutter-apps</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Design]]></category><category><![CDATA[Developer]]></category><category><![CDATA[General Advice]]></category><dc:creator><![CDATA[Alberto Bonacina]]></dc:creator><pubDate>Sat, 27 Mar 2021 13:49:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1616742144436/ng0XuYB-h.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this article, I want to deepen a talk related to Flutter Engage held by <a target="_blank" href="https://twitter.com/filiphracek">@filiphracek</a>, where he presents some ideas for developing beautiful Flutter applications.</p>
<p>We all know that the concept of beauty is subjective, but some tricks can be used to improve the look and feel of our apps and are quite simple to implement. Let's see them together!</p>
<h2 id="white-space">White Space</h2>
<p>This is the first important concept that you have to keep in mind when you develop your app. <strong>White space</strong> is the space between elements that lets them stand out. Trying to fit as much stuff as possible on the screen is often not a good idea because it can make the content difficult to read and make the user lose in the flood of information that is given altogether.</p>
<p>Through the correct use of the spaces between elements, it is possible to communicate what the hierarchy is and therefore the importance or the relationship between elements. The easiest way to implement this first suggestion is through the use of <a target="_blank" href="https://api.flutter.dev/flutter/widgets/Padding-class.html">Padding</a> which allows giving space and air between different elements of our interface. In combination with padding, you should make good use of alignments to communicate even more than elements are related to each other, a very common case is to align the title with the paragraph that corresponds to it so that visually the user can correlate them.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1616824774475/nri4Hdxb-.png" alt="padding-alignment.png" /></p>
<h2 id="typography">Typography</h2>
<p>Another very important concept, especially in those apps that contain a lot of text, is <strong>typography</strong>. Within your app, fonts, and styles you use can give you a great hand in communicating what are the most important elements and what their function is.</p>
<p>A rule that always works is: limit the number of fonts to a minimum, the best would be to use only one family and play with its styles instead: bold, italic, medium, thin. In Flutter there's the <a target="_blank" href="https://pub.dev/packages/google_fonts">google_fonts</a> package to quickly use <a target="_blank" href="https://fonts.google.com/">Google Fonts</a> in your app and play around with fonts until you find the one that best suits your needs, but remembers: less is more.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1616825995640/rcu4HJrRu.png" alt="google_fonts.png" /></p>
<h2 id="color">Color</h2>
<p>You can get a lot in an app using the right combination of colors, certainly, it is not always easy to find the right one but you can always get help from the many online tools that provide already "effective" and beautiful to look at <strong>color palettes</strong> that we can use to improve the look and feel of your app.</p>
<p>Some of these tools such as <a target="_blank" href="https://coolors.co/">Coolors</a> allow you to start from an image and extract the corresponding palette, <a target="_blank" href="https://picular.co/">Picular</a> instead starting from keywords gives you the colors that correspond to it, and finally, <a target="_blank" href="https://mycolor.space/">ColorSpace</a> allows you to generate a color palette from a starting key color, such as the color of your brand.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1616827100945/sm4OI9hEY.png" alt="color_palette.png" /></p>
<p>Once you have chosen the color palette that's right for you, Flutter provides you the <a target="_blank" href="https://api.flutter.dev/flutter/material/ThemeData-class.html">ThemeData</a> class with which you can define the style of your app, use it and make it consistent across all screens and elements.</p>
<h2 id="iconography">Iconography</h2>
<p>Sometimes a picture can say a thousand words, and a picture placed in the right place can do even more. Proper use of icons, images, and graphics can make a huge difference and turn a boring app into a great one.</p>
<p>Flutter provides many classes and packages to work with images, to download them efficiently from the web like <a target="_blank" href="https://pub.dev/packages/cached_network_image">cached_network_image</a>, and to apply a customized icon package: <a target="_blank" href="https://pub.dev/packages/font_awesome_flutter">font_awesome_flutter</a>, <a target="_blank" href="https://pub.dev/packages/fluentui_system_icons">fluentui_system_icons</a> just to name a few.</p>
<p>As mentioned in the case of fonts, if you choose to use a custom icon pack, limit yourself to using only one, in order to keep the style consistent within your app.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1616828703836/Rcu-0LypV.png" alt="icons.png" /></p>
<h2 id="animation">Animation</h2>
<p>This is perhaps the most advanced point of all because with animations it is possible to relate and give life to the elements that are in our apps. Correct use of animations can guide the user within the app, make him naturally switch from one screen to another, or give him feedback on what just happened.</p>
<p>A very easy component to implement in our apps but which can make a big difference is <a target="_blank" href="https://api.flutter.dev/flutter/widgets/Hero-class.html">Hero class</a> with which a component can literally switch between screens continuously. Flutter also allows you to customize the transitions with speed, directions, rotations, leaving you free to customize the interface as you want, even in this case, however, it is always better not to overdo the applied effects too much so as not to make your users seasick.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1616852154281/RVlMLTIxN.png" alt="animation.png" /></p>
<h2 id="conclusion">Conclusion</h2>
<p>In this article, we have seen some very important concepts that can be used within our apps to make them more beautiful and improve the user experience. A package that I can recommend and that can give you a big hand in implementing many customizations of your layouts is <a target="_blank" href="https://twitter.com/imthepk">Pawan Kumar's</a> <a target="_blank" href="https://velocityx.dev/">VelocityX</a> of which I wrote an <a target="_blank" href="https://blog.albertobonacina.com/supercharge-your-flutter-apps-with-velocityx">article</a> a few months ago.
So with everything we learned today let's make our <strong>Flutter apps beautiful!</strong></p>
<p>Bye, Alberto.</p>
<h3 id="links">Links</h3>
<ul>
<li><a target="_blank" href="https://www.youtube.com/watch?v=MIepaf7ks40">The little things: Becoming the mythical designer-developer</a></li>
<li><a target="_blank" href="http://goo.gle/3sggKVe">White space</a></li>
<li><a target="_blank" href="https://dribbble.com/shots/1902171-Design-Principle-Alignment">Design Principle: Alignment</a></li>
<li><a target="_blank" href="https://goo.gle/3bvCXI7">Typography crash course</a></li>
<li><a target="_blank" href="https://goo.gle/3dzK596">Color theory crash course</a></li>
<li><a target="_blank" href="https://goo.gle/3aJxka3">Iconography crash course</a></li>
<li><a target="_blank" href="https://flutter.dev/docs/development/ui/animations">Introduction to animations</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Monetize your Flutter Apps with Google Ads]]></title><description><![CDATA[Hi everyone in this article I want to give you some more information about the recently announced update for Google Ads and Google Ads Manager plugin on Flutter. With this package, you can insert in your app all the supported Ads Format from Google a...]]></description><link>https://blog.albertobonacina.com/monetize-your-flutter-apps-with-google-ads</link><guid isPermaLink="true">https://blog.albertobonacina.com/monetize-your-flutter-apps-with-google-ads</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Google]]></category><category><![CDATA[2Articles1Week]]></category><dc:creator><![CDATA[Alberto Bonacina]]></dc:creator><pubDate>Wed, 24 Mar 2021 07:51:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1616742233753/MSQtQG3MS.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hi everyone in this article I want to give you some more information about the recently announced update for Google Ads and Google Ads Manager plugin on Flutter. With this package, you can insert in your app all the supported Ads Format from Google and monetize your app through them. </p>
<p>With <a target="_blank" href="https://pub.dev/packages/google_mobile_ads">google _mobile_ads</a> package you can choose from these ads format:</p>
<ul>
<li><strong>Banner</strong>: rectangular ads that appear in a fixed position on the screen, usually at the top or bottom, and stays on the screen while the user interacts with your app. Usually is the first banner to try out but with this ad, you lose a portion of your screen;</li>
<li><strong>Interstitial</strong>: a full-screen banner that appears on top of your app and stays there until the user closes it. It's the perfect announcement to show in your app when there is a pause or when the user has just completed an action, such as a level in a game;</li>
<li><strong>Native Ads</strong>: ads that have the same style as your app and you can choose where to place them to interfere as little as possible with the use of your app, often found within lists or content grids;</li>
<li><strong>Rewarded</strong>: ads that reward users for watching it, are often used to give credits or small prizes that can be used within the app.</li>
</ul>
<p>Before releasing this plugin for all developers the Flutter team carried out a private beta program with some customers to test new features, such as Sua Musica (largest Latin American music platform for independent artists with more than 15k verified artists and 10M MAU), and it was seen that there was an increase in Impressions, in the <a target="_blank" href="https://support.google.com/google-ads/answer/2615875?hl=en">CTR</a> and in the <a target="_blank" href="https://support.google.com/admanager/answer/6334268?hl=en">eCPM</a>.</p>
<p>Implementing this new package in your Flutter app is very very simple and with the codelabs you can try out various configurations and use ads that best fit your app. I think this new addition fills a gap that was present until now and allows us, developers, to have an extra monetization possibility.</p>
<p>Bye, Alberto</p>
<h3 id="links">Links</h3>
<ul>
<li><a target="_blank" href="https://flutter.dev/ads">Ads support for Flutter</a></li>
<li><a target="_blank" href="https://pub.dev/packages/google_mobile_ads">google_mobile_ads</a></li>
<li><a target="_blank" href="https://www.youtube.com/watch?v=m0d_pbgeeG8">Monetizing apps with Flutter</a></li>
<li><a target="_blank" href="https://developers.google.com/admob/flutter/quick-start">Mobile Ads SDK (Flutter) Beta</a></li>
<li><a target="_blank" href="https://codelabs.developers.google.com/codelabs/admob-inline-ads-in-flutter#0">Adding an AdMob banner and native inline ads to a Flutter app</a></li>
<li><a target="_blank" href="https://codelabs.developers.google.com/codelabs/admob-ads-in-flutter#0">Adding AdMob ads to a Flutter app</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Foldables and Flutter: very interesting Duo]]></title><description><![CDATA[Foldable devices have recently entered the market and have brought with them new paradigms for browsing and using our apps. Microsoft is very active in this area both with its device: Surface Duo, and the collaboration with the Flutter team to improv...]]></description><link>https://blog.albertobonacina.com/foldables-and-flutter-very-interesting-duo</link><guid isPermaLink="true">https://blog.albertobonacina.com/foldables-and-flutter-very-interesting-duo</guid><category><![CDATA[2Articles1Week]]></category><category><![CDATA[Flutter]]></category><dc:creator><![CDATA[Alberto Bonacina]]></dc:creator><pubDate>Wed, 17 Mar 2021 06:43:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1616742345716/KJKk95iED.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Foldable devices have recently entered the market and have brought with them new paradigms for browsing and using our apps. Microsoft is very active in this area both with its device: <a target="_blank" href="https://www.microsoft.com/en-us/surface/devices/surface-duo">Surface Duo</a>, and the collaboration with the Flutter team to improve support for these types of devices.</p>
<p>In this article, we will look at the navigation patterns present in foldable devices and how these are supported by Flutter.</p>
<h2 id="dual-screen-app-patterns">Dual-screen app patterns</h2>
<p>Dual-screen devices offer developers new ways to build their own apps to make the most of the screen space available. Depending on the type of experience we want to give to our users, patterns have been defined for the arrangement of the contents on the screen:</p>
<ul>
<li><strong>Extended canvas</strong>: this is the simplest way to take advantage of all the space available to us as our app is extended on both screens, this use is recommended for all those applications that have "free" content to show, in which the user can easily navigate it in its entirety such as a map or a canvas for drawing; </li>
<li><strong>List - Detail</strong>: this is another fairly common pattern to exploit and affects all those applications that have a detail-list concept for their content such as messaging or email applications. In this case, the contents of the list (mail, chat, notes) are placed on the left screen and the details of the content are displayed on the right screen;</li>
<li><strong>Two Page</strong>: this pattern is very common and recommended in all those applications that simulate the experience of a book or which by their nature have content that is already paginated or similar to that of a document. In this way it is possible, with a naturally already divided content, to place it on the two screens.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1615962455093/OKsbEmixl.png" alt="dual-screen-app-patterns.png" /></p>
<ul>
<li><strong>Dual View</strong>: this pattern is very interesting when you want to create applications that have the same type of content with two different views, allow the comparison of two similar objects to view the differences or make comparisons. Think for example of an e-commerce application that compares two similar objects or an app for searching for commercial activities that on one screen shows the map with the activities and on the other screen shows the list of information about shops or restaurants; </li>
<li><strong>Companion Pane</strong>: this pattern allows you to take advantage of the additional space made available by the second screen to add complementary information that could not be seen using only a single screen. Very useful for example in all applications that allow users to interact with content by separating the interactive part such as video or images in games or editing applications from the controls like timelines and buttons.</li>
</ul>
<h3 id="orientation">Orientation</h3>
<p>A fundamental role is also given by the orientation of the device which can be used both in portrait mode (left and right screen) and in landscape (screen above and below). In these cases, the simplest way to manage the change of orientation is left &lt;-&gt; above and right &lt;-&gt; below, but depending on the type of application, content, or user, it may be necessary to revise this choice.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1615964277804/wY6iqIHSr.png" alt="list-detail-2-landscape.png" /></p>
<h2 id="flutter-support-for-foldables">Flutter support for Foldables</h2>
<p>Microsoft is actively working with the Flutter team to allow applications to take full advantage of the new form factor and allow applications to be used in both single screen or extended mode across two screens. Several new features have been introduced regarding MediaQuery, Hinge, display features, and the TwoPane widget. Let's give a description:</p>
<ul>
<li><strong>MediaQuery</strong>: class on the Flutter SDK that gives you information about the device screen size, display density, text scaling so you can rearrange your app's content based on that;</li>
<li><strong>Hinge</strong>: is the physical separator between two displays on the device, Surface Duo has a vertical hinge between the two displays, however, the Galaxy Fold has a 0 height horizontal "hinge". </li>
<li><strong>Display features</strong>: lets you query properties of the display that can be non-functional or obstructed, for example, it gives you information about the hinge, fold, cutout, and the state of the devices like halfOpened, flat, flipped;</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1616048854928/As7enwomb.png" alt="twopaneview-surfaceduo-simple.png" /></p>
<ul>
<li><strong>TwoPane widget</strong>: layout that has two child widgets, which can be shown side-by-side, above-and-below, the relative size of the two widgets can be adjusted proportionally; and on dual-screen devices, the boundary snaps to the hinge area.</li>
</ul>
<h2 id="conclusion">Conclusion</h2>
<p>I think that these collaborations between companies on a specific product or technology have the positive effect of making Flutter grows in other aspects as well, one above all the Cross-Platform, as the additions or improvements that seem their own for the Surface Duo can be used to develop better apps for other devices as well.</p>
<p>Bye, Alberto</p>
<h3 id="links">Links</h3>
<ul>
<li><a target="_blank" href="https://devblogs.microsoft.com/surface-duo/flutter-dual-screen-foldable/">Announcing Flutter support for foldable devices</a></li>
<li><a target="_blank" href="https://docs.microsoft.com/en-us/dual-screen/android/">About Surface Duo</a></li>
<li><a target="_blank" href="https://docs.microsoft.com/en-us/dual-screen/introduction">Introduction to dual-screen devices
</a></li>
<li><a target="_blank" href="https://docs.microsoft.com/en-us/dual-screen/flutter/">Get started with Flutter for Surface Duo</a></li>
<li><a target="_blank" href="https://docs.microsoft.com/en-us/dual-screen/flutter/mediaquery">Flutter MediaQuery for Surface Duo</a></li>
<li><a target="_blank" href="https://api.flutter.dev/flutter/widgets/MediaQuery-class.html">MediaQuery class</a></li>
<li><a target="_blank" href="https://docs.microsoft.com/en-us/dual-screen/flutter/twopane-widget">Flutter TwoPane widget</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Sound Null Safety: make better apps with Flutter!]]></title><description><![CDATA[Hi everyone in this article I want to dive deeper into one of the recent announcements made in the Flutter Engage Event: Sound Null Safety. Any of you who have programmed at least once in your life will surely have encountered an error or exception r...]]></description><link>https://blog.albertobonacina.com/sound-null-safety-make-better-apps-with-flutter</link><guid isPermaLink="true">https://blog.albertobonacina.com/sound-null-safety-make-better-apps-with-flutter</guid><category><![CDATA[2Articles1Week]]></category><category><![CDATA[Dart]]></category><category><![CDATA[Flutter]]></category><category><![CDATA[Flutter SDK]]></category><dc:creator><![CDATA[Alberto Bonacina]]></dc:creator><pubDate>Sat, 13 Mar 2021 08:34:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1616742442386/TjZ3qeRiN.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hi everyone in this article I want to dive deeper into one of the recent announcements made in the Flutter Engage Event: <strong>Sound Null Safety</strong>. Any of you who have programmed at least once in your life will surely have encountered an error or exception related to a NULL variable. These errors are often difficult to debug because they occur only during the execution of a program and are difficult to predict during development.</p>
<p>To solve this problem the team of Flutter and Dart have introduced the concept of <strong>Sound Null Safety</strong> which means that types in your code are non-nullable by default and null-dereference errors are no longer "discovered" at runtime but during code writing and this makes your code more secure and less prone to errors at runtime. To better understand how to take advantage of this functionality, let's first introduce some concepts, and then we will move on to the best practices and tools that Flutter provides to make our life easier to make our applications perform better.</p>
<h2 id="definitions">Definitions</h2>
<p>The first thing to keep in mind is that types are <strong>non-nullable by default</strong> unless you explicitly tell Dart that a variable can be null. If you tell Dart that a variable isn’t null, then that thing can NEVER be null and the compiler can make optimizations on your code (because it no longer has to check every time it is used that it is not NULL or "hope" that it is not) and benefits are <strong>fewer bugs</strong>, <strong>smaller binaries</strong>, and <strong>faster execution</strong>. Another important benefit is that you can incrementally migrate your code to null safety, you can mixing null-safe and non-null-safe code in the same project so you can test each part of your app separately until you reach the full migration to null safety. </p>
<p>Now I introduce you to three syntactic operators that help us write safer code or tell the compiler how it should handle a variable: <code>?</code> <code>!</code> and <code>late</code>.</p>
<p>The <code>?</code> operator tells Dart that a variable can have a null value and it doesn’t have to worry because, as good programmers, we add all the code necessary to verify, when we have to use it, that that value is not null</p>
<pre><code class="lang-dart"><span class="hljs-comment">//I declare and assign a variable that can be null</span>
<span class="hljs-built_in">int?</span> iKnowThisVariableWillNoLongerBeNull = <span class="hljs-keyword">null</span>;

<span class="hljs-comment">/*
* Some code that maybe assign a non-null value
*/</span>

<span class="hljs-comment">//Check if the variable is not null</span>
<span class="hljs-keyword">if</span>( iKnowThisVariableWillNoLongerBeNull == <span class="hljs-keyword">null</span> ){
    <span class="hljs-keyword">return</span>;
}

<span class="hljs-comment">//I can use iKnowThisVariableWillNoLongerBeNull </span>
<span class="hljs-comment">//    because is not null and I'm a good programmer ;-)</span>
<span class="hljs-comment">//    so I don't have a runtime error</span>
</code></pre>
<p>The <code>!</code> operator overrides what Dart compiler thinks of a variable because if you are 100% sure that a variable will be not null until it's used and the compiler doesn't have to worry about its value you can add the <code>!</code> operator</p>
<pre><code class="lang-dart"><span class="hljs-comment">//Now I declare and assign a variable that can be null</span>
<span class="hljs-built_in">String?</span> firstVariable = <span class="hljs-string">"Alberto"</span>;

<span class="hljs-comment">/*
* Some code
*/</span>

<span class="hljs-comment">//I'm 100% sure that my variable is not null </span>
<span class="hljs-comment">//    because I assign its value when I declare it</span>
<span class="hljs-comment">//    and I override what Dart thinks</span>
<span class="hljs-built_in">String</span> myName = firstVariable!;
</code></pre>
<p>Another way to tell Dart that a non-nullable variable will be initialized to a non-null value before it’s used is with the <code>late</code> keyword</p>
<pre><code class="lang-dart"><span class="hljs-built_in">int</span> randomNumber(){
    <span class="hljs-comment">//I define a "maybe" null variable but I tell Dart </span>
    <span class="hljs-comment">//    that somewhere in my code I will assign </span>
    <span class="hljs-comment">//    a non-null value</span>
    <span class="hljs-keyword">late</span> <span class="hljs-built_in">int</span> randomNumber;
    <span class="hljs-built_in">int</span> returnedRandomNumber;

    <span class="hljs-comment">//I have fulfilled my promise to assign </span>
    <span class="hljs-comment">//    a non-null value to the variable</span>
    randomNumber = <span class="hljs-number">4</span>;
    returnedRandomNumber = randomNumber;

    <span class="hljs-keyword">return</span> returnedRandomNumber;
}
<span class="hljs-built_in">print</span>(randomNumber()); <span class="hljs-comment">//This string prints the random number 4</span>
</code></pre>
<h2 id="tips-and-tools">Tips &amp; Tools</h2>
<p>If you want to migrate your app to null safety the Flutter team provides you some useful tools to make this migration easy. First of all, check that you have Dart 2.12 or later installed with Flutter &gt; 2.x.x, you can check it with</p>
<pre><code class="lang-bash">$ dart --version

Dart SDK version: 2.12.0 (stable) (Thu Feb 25 19:50:53 2021 +0100) on <span class="hljs-string">"linux_x64"</span>
</code></pre>
<p>After that, you have to keep in mind that before migrating your actual code you should wait until all packages your app depends on have been migrated to null safety, to check it run</p>
<pre><code class="lang-bash">dart pub outdated --mode=null-safety
</code></pre>
<p>This is a simple output and if in the <em>Resolvable</em> column all the packages have a green checkmarked version all of your dependencies are already migrated to null safety and you can upgrade </p>
<p><img src="https://dart.dev/null-safety/pub-outdated-output.png" alt="pub-outdated-output" /></p>
<p>If any of your package’s dependencies don’t yet support null safety, you can reach out to the package owner and tell if a null-safety release of the package is in work and you can help with something. If all is green you can upgrade all of your dependencies, and update the <code>pubspec.yaml</code> file, with </p>
<pre><code class="lang-bash">$ dart pub upgrade --null-safety
$ dart pub get
</code></pre>
<p>The last step is to migrate your actual code with </p>
<pre><code class="lang-bash">$ dart migrate
</code></pre>
<p>If all it's ok and your app is ready to migrate, then you should see an output like this</p>
<pre><code class="lang-bash">View the migration suggestions by visiting:

  http://127.0.0.1:60278/Users/you/project/mypkg.console-simple?authToken=Xfz0jvpyeMI%3D
</code></pre>
<p>Going in that webpage you will see what changes Dart proposes for your code and you can apply all the changes in one shot, apply changes only to certain parts of your app, or review them and apply by hand. The Flutter team suggests applying changes only to one part of your app at a time and test them until you reach the full migration.</p>
<p>If you start from scratch with a brand new app and you want to have null safety from day 0 you have to create your project with</p>
<pre><code class="lang-bash"> $ dart create -t console-full my_brand_new_app
 $ <span class="hljs-built_in">cd</span> my_brand_new_app
 $ dart migrate --apply-changes
</code></pre>
<h3 id="conclusion">Conclusion</h3>
<p>I think that <strong>Sound Null Safety</strong> is a wonderful addition to Dart and Flutter because it forces us to think more about our code and to write it better, it makes our apps faster and with fewer bugs. If you want to experiment with Null Safety in Dart before diving in to introduce it in your apps you can use the <a target="_blank" href="https://nullsafety.dartpad.dev/">DartPad with null safety</a>.</p>
<p>Bye, Alberto </p>
<h4 id="links">Links</h4>
<ul>
<li><a target="_blank" href="https://dart.dev/null-safety/understanding-null-safety">Understanding null safety</a></li>
<li><a target="_blank" href="https://dart.dev/null-safety/migration-guide">Migrating to null safety</a></li>
<li><a target="_blank" href="https://dart.dev/null-safety/tour">Null safety feature tour</a></li>
<li><a target="_blank" href="https://dart.dev/null-safety">Sound null safety</a></li>
<li><a target="_blank" href="https://dart.dev/null-safety/faq">Null safety: frequently asked questions</a></li>
<li><a target="_blank" href="https://github.com/dart-lang/samples/tree/master/null_safety/calculate_lix">Null safety example: A CLI app for calculating lix</a></li>
</ul>
]]></content:encoded></item></channel></rss>