<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Abhijeet Singh</title>
    <description>The latest articles on DEV Community by Abhijeet Singh (@abjt14).</description>
    <link>https://dev.to/abjt14</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F821631%2F5373425f-6d7d-4349-b163-e0fd79df6725.jpeg</url>
      <title>DEV Community: Abhijeet Singh</title>
      <link>https://dev.to/abjt14</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/abjt14"/>
    <language>en</language>
    <item>
      <title>Calculating Transparency of an HTML5 Canvas</title>
      <dc:creator>Abhijeet Singh</dc:creator>
      <pubDate>Fri, 17 Mar 2023 00:57:32 +0000</pubDate>
      <link>https://dev.to/abjt14/calculating-transparency-of-an-html5-canvas-14lh</link>
      <guid>https://dev.to/abjt14/calculating-transparency-of-an-html5-canvas-14lh</guid>
      <description>&lt;p&gt;Alright let's get back to basics here. HTML5 Canvas is a very versatile element capable of both 2d and 3d graphics. It is used in majority of the eye-candy websites featured on websites like &lt;a href="https://www.awwwards.com/"&gt;awwwards.com&lt;/a&gt; and &lt;a href="https://www.siteinspire.com/"&gt;siteinspire.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While building one of my older &lt;a href="https://portfolio-v4-abjt14.vercel.app/"&gt;portfolio websites&lt;/a&gt;, I built a drawable background that auto-fills once half the Canvas has been drawn on. In order to make this work, I had to calculate the transparency percentage of the Canvas.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You wouldn't believe how simple this can be.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For this article, we'll need to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create A Canvas&lt;/li&gt;
&lt;li&gt;Draw A Shape&lt;/li&gt;
&lt;li&gt;Calculate Transparency&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Alright onto &lt;strong&gt;Step 1&lt;/strong&gt;. Let's create a basic HTML Canvas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;canvas&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"500"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"500"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're already at &lt;strong&gt;Step 2?&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// get the context&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;canvas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2d&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// add a shape&lt;/span&gt;
&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fillStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#000000&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fillRect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3.&lt;/strong&gt; Finally we get to write some logic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// retrieving image data&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imageData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getImageData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's check the &lt;code&gt;imageData&lt;/code&gt; values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;imageData&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;imageData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// we get the following array of 1000000 values&lt;/span&gt;
&lt;span class="c1"&gt;// [0, 0, 0, 255, 0, 0, 0, 255............, 1, 1, 1, 255, 1, 1, 1, 255]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you might have guessed, these are &lt;code&gt;rgba&lt;/code&gt; values of each pixel in the canvas, defining the Red, Green, Blue, and Alpha (transparency) values respectively. Each value ranges from &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;255&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What we have to focus on here, is the Alpha values. So let's isolate them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// removing every non-4th value (rgb values)&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;alphaValues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;imageData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The method to calculate transparency is pretty simple, we just need the transparent pixels and the total pixel count.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// reworking the filter to remove non-zero alpha values as well&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;alphaValues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;imageData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// get the maximum pixel count&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;maxPixels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now for the finale, let's calculate the transparency ratio and convert it to a percentage.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// tada!&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;percentage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;alphaValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;maxPixels&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// a good old fashioned console.log()&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;percentage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;%`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// "75%"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's all folks, told ya it was simple.&lt;/p&gt;

</description>
      <category>html</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Bongo Copy Cat: A Tauri Cat that wants to be involved in everything you do 👨‍💻👩‍💻</title>
      <dc:creator>Abhijeet Singh</dc:creator>
      <pubDate>Thu, 19 Jan 2023 00:43:52 +0000</pubDate>
      <link>https://dev.to/abjt14/bongo-copy-cat-a-tauri-cat-that-wants-to-be-involved-in-everything-you-do-5bge</link>
      <guid>https://dev.to/abjt14/bongo-copy-cat-a-tauri-cat-that-wants-to-be-involved-in-everything-you-do-5bge</guid>
      <description>&lt;p&gt;&lt;strong&gt;Bongo Copy Cat&lt;/strong&gt; wants to be involved in everything you do but instead just imitates you hitting your keyboard all day. After all it's just a cat 🐈.&lt;/p&gt;

&lt;p&gt;I am new to &lt;a href="https://www.rust-lang.org/" rel="noopener noreferrer"&gt;Rust&lt;/a&gt;, and this is my first project built using the awesome programming language.&lt;/p&gt;

&lt;p&gt;Check out the project on &lt;a href="https://github.com/abjt14/bongo-copy-cat" rel="noopener noreferrer"&gt;github&lt;/a&gt;. The documentation includes the &lt;code&gt;executables&lt;/code&gt; and as well as instructions on building it locally.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/abjt14" rel="noopener noreferrer"&gt;
        abjt14
      &lt;/a&gt; / &lt;a href="https://github.com/abjt14/bongo-copy-cat" rel="noopener noreferrer"&gt;
        bongo-copy-cat
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Bongo Copy Cat wants to be involved in everything you do but instead just imitates you hitting your keyboard all day. After all it's just a cat.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Bongo Copy Cat&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/abjt14/bongo-copy-cat/main/main.gif"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fabjt14%2Fbongo-copy-cat%2Fmain%2Fmain.gif" width="25%" height="25%"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.rust-lang.org/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/981f88cd65e622bc3783777e750b55ad440808301fcc87b4be00864a5760aba7/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4d616465253230776974682d527573742d3166343235662e737667" alt="made-with-rust"&gt;&lt;/a&gt; &lt;a href="https://github.com/abjt14/bongo-copy-cat/actions/workflows/main.yml" rel="noopener noreferrer"&gt;&lt;img src="https://github.com/abjt14/bongo-copy-cat/actions/workflows/main.yml/badge.svg" alt="Build"&gt;&lt;/a&gt; &lt;a href="https://opensource.org/licenses/MIT" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/28f4d479bf0a9b033b3a3b95ab2adc343da448a025b01aefdc0fbc7f0e169eb8/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e2e737667" alt="License"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Introduction&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Bongo Copy Cat&lt;/strong&gt; wants to be involved in everything you do but instead just imitates you hitting your keyboard all day. After all it's just a cat.&lt;/p&gt;
&lt;p&gt;A desktop app built using the &lt;a href="https://tauri.app/" rel="nofollow noopener noreferrer"&gt;&lt;strong&gt;Tauri&lt;/strong&gt;&lt;/a&gt; framework. Supported platforms: &lt;code&gt;MacOS&lt;/code&gt; and &lt;code&gt;Windows&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is a practice project for me to learn &lt;strong&gt;Rust&lt;/strong&gt; and &lt;strong&gt;Tauri&lt;/strong&gt;. Read more about the idea on my &lt;a href="https://abjt.dev/writing/bongo-copy-cat" rel="nofollow noopener noreferrer"&gt;blog&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here's the app in action
&lt;a rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/abjt14/bongo-copy-cat/main/main-2.gif"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fabjt14%2Fbongo-copy-cat%2Fmain%2Fmain-2.gif"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;About the meme&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Bongo Cat is a meme created by &lt;a href="https://twitter.com/DitzyFlama" rel="nofollow noopener noreferrer"&gt;DitzyFlama&lt;/a&gt; (&lt;a href="https://twitter.com/DitzyFlama/status/993487015499853824" rel="nofollow noopener noreferrer"&gt;tweet&lt;/a&gt;) using &lt;a href="https://twitter.com/StrayRogue" rel="nofollow noopener noreferrer"&gt;StrayRogue&lt;/a&gt;'s &lt;a href="https://twitter.com/StrayRogue/status/992994454058381312" rel="nofollow noopener noreferrer"&gt;drawing of a cat&lt;/a&gt;.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Libraries that made this possible&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/Narsil/rdev" rel="noopener noreferrer"&gt;Rdev&lt;/a&gt; for listening to global input events on Mac OS.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/obv-mikhail/InputBot" rel="noopener noreferrer"&gt;InputBot&lt;/a&gt; for listening to global input events on Windows.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Installation Methods&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Download exectuables for &lt;code&gt;MacOS&lt;/code&gt; and &lt;code&gt;Windows&lt;/code&gt; from the &lt;a href="https://github.com/abjt14/bongo-copy-cat/releases" rel="noopener noreferrer"&gt;releases&lt;/a&gt; page.&lt;/li&gt;
&lt;li&gt;Build it yourself.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Building&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;You can always build the project youself. This will prevent the system from throwing warnings while…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/abjt14/bongo-copy-cat" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Backstory 💬

&lt;ul&gt;
&lt;li&gt;Dilemma&lt;/li&gt;
&lt;li&gt;Inspiration&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Development 🧑‍💻

&lt;ul&gt;
&lt;li&gt;Research&lt;/li&gt;
&lt;li&gt;Challenges&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Wrap Up 🎙️&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Dilemma
&lt;/h2&gt;

&lt;p&gt;So here's the story. I decided to learn &lt;code&gt;Rust&lt;/code&gt;, read the &lt;a href="https://doc.rust-lang.org/book/" rel="noopener noreferrer"&gt;docs&lt;/a&gt;, solved the &lt;a href="https://github.com/rust-lang/rustlings" rel="noopener noreferrer"&gt;rustlings&lt;/a&gt; challenges. The next step in learning a new programming language is to build something with it. And so began my dilemma.&lt;/p&gt;

&lt;p&gt;I can always build a simple todo app, a calculator, or something more &lt;a href="https://github.com/codecrafters-io/build-your-own-x" rel="noopener noreferrer"&gt;challenging&lt;/a&gt;. But I am a creative, the urge to build something unique is too strong. And so I started brainstorming ideas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspiration
&lt;/h2&gt;

&lt;p&gt;A few weeks go by, I move on to my art projects while taking time out to find something fun to build with &lt;code&gt;Rust&lt;/code&gt;. I know I know, this is not going good.&lt;/p&gt;

&lt;p&gt;One night, as I was scrolling through Instagram, watching videos of cats, procrastinating going to sleep, I found my project.&lt;/p&gt;

&lt;p&gt;There was a video of a lady explaining how she stopped her cat from sitting on her laptop while she works from home. She claimed that cats want to copy you, be involved in what you do, so how about we give the cat a laptop? She got her cat a mini toy laptop and it worked! While the lady was busy striking the keys on her laptop, the cat played with the toy pretending to work.&lt;/p&gt;

&lt;p&gt;And so I thought, what if the &lt;a href="https://knowyourmeme.com/memes/bongo-cat" rel="noopener noreferrer"&gt;Bongo Cat&lt;/a&gt; copied me working on my laptop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Research
&lt;/h2&gt;

&lt;p&gt;First, I made a list of the requirements.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A &lt;strong&gt;Rust&lt;/strong&gt; based global input listener that can listen to the keyboard events even if the app isn't in focus.&lt;/li&gt;
&lt;li&gt;A cross-platform &lt;strong&gt;Rust&lt;/strong&gt; framework so I can target multiple platforms.&lt;/li&gt;
&lt;li&gt;An app to draw the cat meme.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I assumed that my research to find a &lt;code&gt;Rust&lt;/code&gt; based &lt;code&gt;global input listener&lt;/code&gt; will lead me to Stack Overflow, instead I found my answers on Reddit.&lt;/p&gt;

&lt;p&gt;The two &lt;code&gt;crates&lt;/code&gt; I found that worked for my use-case were &lt;a href="https://github.com/Narsil/rdev" rel="noopener noreferrer"&gt;Rdev&lt;/a&gt; and &lt;a href="https://github.com/obv-mikhail/InputBot" rel="noopener noreferrer"&gt;InputBot&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tauri.app/" rel="noopener noreferrer"&gt;Tauri&lt;/a&gt; was the obvious choice for the cross platform application. With &lt;code&gt;57.3K&lt;/code&gt; stars on Github and growing, it is a framework loved by the community. It combines your favourite frontend frameworks with a &lt;code&gt;Rust&lt;/code&gt; backend to build "smaller, faster, and more secure desktop applications".&lt;/p&gt;

&lt;p&gt;Lastly, I wanted a drawing app for my simple use-case. Since I love open source apps, I chose &lt;a href="https://krita.org/en/" rel="noopener noreferrer"&gt;Krita&lt;/a&gt;. It may be an overkill, but I have wanted to learn the application for a while so I can use it with my other projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenges
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Rdev&lt;/code&gt; supported Window, MacOS, and Linux, but &lt;code&gt;InputBot&lt;/code&gt; only supports Windows and Linux. Since I develop on a &lt;code&gt;Mac OS&lt;/code&gt; system, I tested &lt;code&gt;Rdev&lt;/code&gt; first.&lt;/p&gt;

&lt;p&gt;Both libraries had partial support for linux and I had trouble getting them to work in my &lt;code&gt;Tauri&lt;/code&gt; project. So I've skipped building the app for linux.&lt;/p&gt;

&lt;p&gt;The next hurdle I ran into was the &lt;code&gt;global event listener&lt;/code&gt; library itself. The GitHub documentation of &lt;code&gt;Rdev&lt;/code&gt; mentions a few OS specific caveats in addition to the fact that the &lt;code&gt;listener&lt;/code&gt; is "blocking".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;rdev&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// This will block.&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error: {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"My callback {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="py"&gt;.name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"User wrote {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nb"&gt;None&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While it was easy to get it working as a standalone &lt;code&gt;Rust&lt;/code&gt; program, running the loop blocked &lt;code&gt;Tauri&lt;/code&gt; from building the application.&lt;/p&gt;

&lt;p&gt;After a lot of research and testing, I found that one way to make it work was to use the loop inside a &lt;code&gt;tauri::command&lt;/code&gt; that can be &lt;code&gt;invoked&lt;/code&gt; from the frontend once the application has loaded.&lt;/p&gt;

&lt;p&gt;Here I define the &lt;code&gt;tauri::command&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[tauri::command]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Window&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;emit_event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="nf"&gt;.eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"document.querySelector('button').click()"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error: {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;callback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="py"&gt;.name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;emit_event&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="nb"&gt;None&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error: {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we need to use a &lt;code&gt;Closure Function&lt;/code&gt; of the following form if we want to capture &lt;code&gt;variables&lt;/code&gt; inside an inner function. For more details on why we have to do this, check out this answer on &lt;a href="https://stackoverflow.com/a/54367316" rel="noopener noreferrer"&gt;Stack Overflow&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;closure_fn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="n"&gt;stuff&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to communicate with the frontend, I used the &lt;code&gt;window.eval()&lt;/code&gt; function to click on an &lt;code&gt;HTML&lt;/code&gt; button I have in my &lt;code&gt;index.html&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Now that my app was running on Mac OS, I decided to test it on Windows. Unfortunately, as soon as the application launched, it crashed. After some testing, I figured out that the &lt;code&gt;listener&lt;/code&gt; is blocking &lt;code&gt;Tauri&lt;/code&gt; from running the app.&lt;/p&gt;

&lt;p&gt;I tried using &lt;code&gt;multithreading&lt;/code&gt; to prevent the &lt;code&gt;listener&lt;/code&gt; from blocking but it didn't work. Since I couldn't figure out how to fix this, I decided to test the other library called &lt;code&gt;InputBot&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The Github repository for the library has an example code snippet to bind all keys to the listener. Since this function wasn't blocking, it worked seamlessly without any issues.&lt;/p&gt;

&lt;p&gt;Separating the &lt;code&gt;dependencies&lt;/code&gt; and &lt;code&gt;imports&lt;/code&gt; based on the operating system was pretty easy as it is supported by &lt;code&gt;Rust&lt;/code&gt; out of the box.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;cargo.toml&lt;/code&gt;, I defined the &lt;code&gt;conditional dependencies&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[target.'cfg(windows)'.dependencies]&lt;/span&gt;
&lt;span class="py"&gt;inputbot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;git&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https://github.com/obv-mikhail/InputBot"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;branch&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"develop"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nn"&gt;[target.'cfg(unix)'.dependencies]&lt;/span&gt;
&lt;span class="py"&gt;rdev&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.5.2"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in my &lt;code&gt;main.rs&lt;/code&gt; file, I used &lt;code&gt;conditional imports&lt;/code&gt; and &lt;code&gt;functions&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[cfg(target_os&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"macos"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;rdev&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nd"&gt;#[cfg(target_os&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"windows"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;inputbot&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;KeybdKey&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;#[cfg(target_os&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"macos"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="nd"&gt;#[tauri::command]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Window&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// code using "rdev"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[cfg(target_os&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"windows"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="nd"&gt;#[tauri::command]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Window&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// code using "inputBot"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, the &lt;code&gt;Tauri&lt;/code&gt; docs made it really easy to setup a Github Workflow to automate release builds. It's plug and play. Kudos to the contributors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap Up
&lt;/h2&gt;

&lt;p&gt;Here's the app in action.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9omordcikzf2cvrglmny.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9omordcikzf2cvrglmny.gif" alt="The app in action" width="1024" height="1024"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.rust-lang.org/" rel="noopener noreferrer"&gt;Rust&lt;/a&gt; is awesome. I find "fixing bugs and issues" to be a great way to learn a new language/library/framework. The &lt;code&gt;rust compiler&lt;/code&gt; makes you a better developer, allowing you to use good programming habits in other languages as well. Learning &lt;code&gt;Rust&lt;/code&gt; means practice, practice, practice. And I'm gonna do just that.&lt;/p&gt;

&lt;p&gt;Github Workflows is a lot simpler than I thought. I assumed it to have complicated code and low community support. I couldn't have been more wrong.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tauri.app/" rel="noopener noreferrer"&gt;Tauri&lt;/a&gt; is an solid framework with a bright future. I know I have only scratched the surface here, but I look forward to building more complex applications in future.&lt;/p&gt;

&lt;p&gt;For developers new to &lt;code&gt;Rust&lt;/code&gt;, please understand that the one thing that makes the language difficult to learn is the approach it takes towards coding. Take your time to understand the system. It makes you a better developer, allowing you to use good programming habits in other languages as well.&lt;/p&gt;

&lt;p&gt;I commend the &lt;code&gt;Rust&lt;/code&gt; community and all the &lt;code&gt;Rustaceans&lt;/code&gt; for creating such an amazing ecosystem.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is my first blog post on this website. I appreciate all the questions and suggestions. Thank you for reading ❤️&lt;/em&gt;&lt;/p&gt;

</description>
      <category>motivation</category>
    </item>
  </channel>
</rss>
