DEV Community: Davyd NRB
The latest articles on DEV Community by Davyd NRB (@retyui).
https://dev.to/retyui
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%2F162965%2F8f92c752-f9da-474e-b34f-2cd10bb6b1dd.gif
DEV Community: Davyd NRB
https://dev.to/retyui
en
-
π¨ 99% of React Native Apps Make This Localization (i18n) Mistake β Is Yours One of Them?
Davyd NRB
Fri, 01 Aug 2025 09:02:27 +0000
https://dev.to/retyui/99-of-react-native-apps-make-this-localization-i18n-mistake-is-yours-one-of-them-2o6g
https://dev.to/retyui/99-of-react-native-apps-make-this-localization-i18n-mistake-is-yours-one-of-them-2o6g
<p>One of the most common (and costly) mistakes in multilingual React Native apps is <strong>bundling all localization files directly into the JavaScript bundle</strong>.</p>
<p>If your app supports several languages (for example: English, Spanish, French, etc.) and youβre still bundling them into JS, youβre doing it the wrong way.</p>
<p>But donβt worry β <strong>99% of us have done this</strong>.</p>
<h2>
πͺ€ The Problem
</h2>
<p>Hereβs what happens when all locale files are bundled in JS:</p>
<ul>
<li>π Increased app size</li>
<li>π’ Slower app startup</li>
<li>π§ Higher memory usage (even for unused languages)</li>
</ul>
<p>This might be fine in development, but it's a performance killer in production.</p>
<h2>
β
The Right Way (Android)
</h2>
<p>Letβs fix it using two native Android features:</p>
<ul>
<li><strong><a href="proxy.php?url=https://developer.android.com/guide/topics/resources/app-languages" rel="noopener noreferrer">Per-app language preferences</a></strong></li>
<li><strong><a href="proxy.php?url=https://developer.android.com/guide/topics/resources/providing-resources" rel="noopener noreferrer">Alternative resources</a> based on device locale</strong></li>
</ul>
<h3>
Step 1: Move Locale Files to Native Resources
</h3>
<p>Instead of bundling JSON locale files in JS, place them in Android's raw resource folders:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight plaintext"><code>android/
βββ app/
βββ src/
βββ main/
βββ res/
βββ raw/ # default (e.g. English)
β βββ localizable.json
βββ raw-es/ # Spanish
β βββ localizable.json
βββ raw-fr/ # French
β βββ localizable.json
βββ raw-it/ # Italian
β βββ localizable.json
βββ raw-pt-rBR/ # Portuguese (Brazil)
β βββ localizable.json
</code></pre>
</div>
<p>Now, Android will include <strong>only the necessary languages</strong> based on the user's device settings.</p>
<h3>
Step 2: Enable Per-App Language Preferences
</h3>
<p>Let Android handle locale selection automatically.</p>
<h4>
2.1 Create <code>locales_config.xml</code>
</h4>
<div class="highlight js-code-highlight">
<pre class="highlight xml"><code><span class="cp"><?xml version="1.0" encoding="utf-8"?></span>
<span class="nt"><locale-config</span> <span class="na">xmlns:android=</span><span class="s">"http://schemas.android.com/apk/res/android"</span><span class="nt">></span>
<span class="nt"><locale</span> <span class="na">android:name=</span><span class="s">"en"</span><span class="nt">/></span>
<span class="nt"><locale</span> <span class="na">android:name=</span><span class="s">"es"</span><span class="nt">/></span>
<span class="nt"><locale</span> <span class="na">android:name=</span><span class="s">"fr"</span><span class="nt">/></span>
<span class="nt"><locale</span> <span class="na">android:name=</span><span class="s">"it"</span><span class="nt">/></span>
<span class="nt"><locale</span> <span class="na">android:name=</span><span class="s">"pt-br"</span><span class="nt">/></span>
<span class="nt"></locale-config></span>
</code></pre>
</div>
<p>Save this file to:<br>
<code>android/app/src/main/res/xml/locales_config.xml</code></p>
<h4>
2.2 Register in <code>AndroidManifest.xml</code>
</h4>
<div class="highlight js-code-highlight">
<pre class="highlight diff"><code><application
android:name=".MainApplication"
android:label="@string/app_name"
<span class="gi">+ android:localeConfig="@xml/locales_config"
</span></code></pre>
</div>
<h4>
2.3 Configure <code>resConfigs</code> in <code>build.gradle</code>
</h4>
<p>In <code>android/app/build.gradle</code>, declare the supported locales:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight groovy"><code><span class="n">android</span> <span class="o">{</span>
<span class="n">defaultConfig</span> <span class="o">{</span>
<span class="o">...</span>
<span class="n">resConfigs</span> <span class="s2">"en"</span><span class="o">,</span> <span class="s2">"es"</span><span class="o">,</span> <span class="s2">"fr"</span><span class="o">,</span> <span class="s2">"it"</span><span class="o">,</span> <span class="s2">"pt-rBR"</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre>
</div>
<h2>
π Bonus: Read Locales from Native Side
</h2>
<p>Now that your locales live natively, itβs time to read them.</p>
<p>In production, use the native resource. In development, load the file directly for faster iteration:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight typescript"><code><span class="k">import</span> <span class="p">{</span> <span class="nx">Fbtee</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">react-native-fbtee</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">function</span> <span class="nf">getLocale</span><span class="p">()</span> <span class="p">{</span>
<span class="k">if </span><span class="p">(</span><span class="nx">__DEV__</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nf">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">../android/app/src/main/res/raw/localizable.json</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">JSON</span><span class="p">.</span><span class="nf">parse</span><span class="p">(</span><span class="nx">Fbtee</span><span class="p">.</span><span class="nf">readLocalizationFile</span><span class="p">(</span><span class="dl">'</span><span class="s1">localizable</span><span class="dl">'</span><span class="p">));</span>
<span class="p">}</span>
</code></pre>
</div>
<blockquote>
<p>π¦ <a href="proxy.php?url=https://www.npmjs.com/package/react-native-fbtee" rel="noopener noreferrer"><code>react-native-fbtee</code></a> enables fast, synchronous file access from native resources.</p>
</blockquote>
<h2>
π§© Putting It All Together
</h2>
<p>Here's what happens in practice:</p>
<ol>
<li>π² User installs your app.</li>
<li>π₯ Only the locale matching their device is downloaded.</li>
<li>π If they change the app language (via system settings), Android <strong>dynamically downloads</strong> the new locale in the background.</li>
<li>π¦ Your app reads the updated locale JSON β no JS bundle changes needed.</li>
</ol>
<p>Often, this triggers a push notification like:</p>
<p><a href="proxy.php?url=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%2F2oasd8pymtxaihpiz37p.png" class="article-body-image-wrapper"><img src="proxy.php?url=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%2F2oasd8pymtxaihpiz37p.png" alt=" " width="800" height="758"></a></p>
<p>Once the download completes, translations are updated β you can read updated values.</p>
<h2>
π Verify It: Check Your App Size
</h2>
<p>Tools like <strong><a href="proxy.php?url=https://engineering.atspotify.com/2022/2/introducing-ruler-our-tool-for-measuring-android-app-size/" rel="noopener noreferrer">Ruler by Spotify</a></strong> can show the difference in download size per locale. Youβll be shocked at how much space you save (π see a demo video <a href="proxy.php?url=https://www.youtube.com/watch?v=Ud6TSlnEzCc&t=93s" rel="noopener noreferrer">from MichaΕ PierzchaΕa</a>)..</p>
<p><a href="proxy.php?url=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%2Fbndmuq5aovy13uo6ldvn.png" class="article-body-image-wrapper"><img src="proxy.php?url=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%2Fbndmuq5aovy13uo6ldvn.png" width="800" height="334"></a></p>
<h2>
TL;DR
</h2>
<div class="table-wrapper-paragraph"><table>
<thead>
<tr>
<th>β Donβt do this...</th>
<th>β
Do this instead</th>
</tr>
</thead>
<tbody>
<tr>
<td>Bundle all locales in JS</td>
<td>Use native raw resources</td>
</tr>
<tr>
<td>Load all languages in memory</td>
<td>Let Android handle locale</td>
</tr>
<tr>
<td>Rebuild for every change</td>
<td>Load dynamically from native (dev. mode only)</td>
</tr>
</tbody>
</table></div>
-
Boost Your React Native App Start Time: Stop Shipping Lottie JSON Incorrectly
Davyd NRB
Sun, 27 Jul 2025 17:33:10 +0000
https://dev.to/retyui/boost-your-react-native-app-start-time-stop-shipping-lottie-json-incorrectly-2074
https://dev.to/retyui/boost-your-react-native-app-start-time-stop-shipping-lottie-json-incorrectly-2074
<p>I've been analyzing many <strong>React Native JavaScript bundles</strong> (which you can find on Twitter: <a href="proxy.php?url=https://x.com/tell_me_mur" rel="noopener noreferrer">https://x.com/tell_me_mur</a>) and have noticed a critical mistake that almost everyone is making. This error significantly impacts your application's <strong>App Start Time (AST)</strong> and <strong>memory usage</strong>.</p>
<p>The screenshot below illustrates how the JS bundle is overloaded with numerous i18n locales and Lottie animations (JSON files).</p>
<p><a href="proxy.php?url=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%2Fc3hda64q9esmpelhlfzn.webp" class="article-body-image-wrapper"><img src="proxy.php?url=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%2Fc3hda64q9esmpelhlfzn.webp" width="800" height="396"></a></p>
<p>Do you need all locales and animations when the user launches the application? The answer is NO. </p>
<p>You'll only need JSON files at specific moments when using your application. Therefore, it's best to handle them as assets and load them on demand.</p>
<h2>
How to Load Lottie JSON as Assets On Demand
</h2>
<h3>
Move JSON files to the assets directory.
</h3>
<p>For Android, move all JSON animation files to:<br>
<code>android/app/src/main/assets/*.json</code></p>
<p>For iOS applications, you can reuse the same files from the Android directory for linking on iOS. To do this, run the following command:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight shell"><code>npx react-native-asset <span class="nt">--ios-assets</span> android/app/src/main/assets
</code></pre>
</div>
<p>The files will be successfully added and ready for use. <em>Remember to rebuild your application if you are in development mode</em>.</p>
<h3>
Read the asset files.
</h3>
<p>Your project might already have a library for file operations, such as <code>react-native-fs</code>, <code>react-native-blob-util</code>, or <code>react-native-file-access</code>. If not, install one of your choice.</p>
<p>Below are code examples for each of these libraries:</p>
<h4>
<code>react-native-fs</code>
</h4>
<div class="highlight js-code-highlight">
<pre class="highlight typescript"><code><span class="k">import</span> <span class="p">{</span> <span class="nx">Platform</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">react-native</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">readFileRes</span><span class="p">,</span> <span class="nx">readFile</span><span class="p">,</span> <span class="nx">MainBundlePath</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">react-native-fs</span><span class="dl">'</span><span class="p">;</span>
<span class="k">export</span> <span class="k">async</span> <span class="kd">function</span> <span class="nf">readAsset</span><span class="p">(</span><span class="nx">name</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="nb">Promise</span><span class="o"><</span><span class="kr">string</span> <span class="o">|</span> <span class="kc">null</span><span class="o">></span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="k">if </span><span class="p">(</span><span class="nx">Platform</span><span class="p">.</span><span class="nx">OS</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">android</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">content</span> <span class="o">=</span> <span class="k">await</span> <span class="nf">readFileRes</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="dl">'</span><span class="s1">utf8</span><span class="dl">'</span><span class="p">);</span>
<span class="k">return</span> <span class="nx">content</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">const</span> <span class="nx">path</span> <span class="o">=</span> <span class="s2">`</span><span class="p">${</span><span class="nx">MainBundlePath</span><span class="p">}</span><span class="s2">/</span><span class="p">${</span><span class="nx">name</span><span class="p">}</span><span class="s2">`</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">content</span> <span class="o">=</span> <span class="k">await</span> <span class="nf">readFile</span><span class="p">(</span><span class="nx">path</span><span class="p">,</span> <span class="dl">'</span><span class="s1">utf8</span><span class="dl">'</span><span class="p">);</span>
<span class="k">return</span> <span class="nx">content</span><span class="p">;</span>
<span class="p">}</span> <span class="k">catch </span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nf">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Error reading asset:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">e</span><span class="p">);</span>
<span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Usage example</span>
<span class="nf">readAsset</span><span class="p">(</span><span class="dl">'</span><span class="s1">animation.json</span><span class="dl">'</span><span class="p">)</span>
<span class="p">.</span><span class="nf">then</span><span class="p">(</span><span class="nx">jsonStr</span> <span class="o">=></span> <span class="nx">JSON</span><span class="p">.</span><span class="nf">parse</span><span class="p">(</span><span class="nx">jsonStr</span><span class="p">))</span>
<span class="p">.</span><span class="nf">then</span><span class="p">(</span><span class="nx">data</span> <span class="o">=></span> <span class="p">{</span>
<span class="c1">// your logic</span>
<span class="p">});</span>
</code></pre>
</div>
<h4>
<code>react-native-blob-util</code>
</h4>
<div class="highlight js-code-highlight">
<pre class="highlight typescript"><code><span class="k">import</span> <span class="nx">RNFetchBlob</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">react-native-blob-util</span><span class="dl">'</span><span class="p">;</span>
<span class="k">export</span> <span class="k">async</span> <span class="kd">function</span> <span class="nf">readAsset</span><span class="p">(</span><span class="nx">name</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="nb">Promise</span><span class="o"><</span><span class="kr">string</span> <span class="o">|</span> <span class="kc">null</span><span class="o">></span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">path</span> <span class="o">=</span> <span class="nx">RNFetchBlob</span><span class="p">.</span><span class="nx">fs</span><span class="p">.</span><span class="nf">asset</span><span class="p">(</span><span class="nx">name</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">content</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">RNFetchBlob</span><span class="p">.</span><span class="nx">fs</span><span class="p">.</span><span class="nf">readFile</span><span class="p">(</span><span class="nx">path</span><span class="p">,</span> <span class="dl">'</span><span class="s1">utf8</span><span class="dl">'</span><span class="p">);</span>
<span class="k">return</span> <span class="nx">content</span><span class="p">;</span>
<span class="p">}</span> <span class="k">catch </span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nf">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Error reading asset:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">e</span><span class="p">);</span>
<span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Usage example</span>
<span class="nf">readAsset</span><span class="p">(</span><span class="dl">'</span><span class="s1">animation.json</span><span class="dl">'</span><span class="p">)</span>
<span class="p">.</span><span class="nf">then</span><span class="p">(</span><span class="nx">jsonStr</span> <span class="o">=></span> <span class="nx">JSON</span><span class="p">.</span><span class="nf">parse</span><span class="p">(</span><span class="nx">jsonStr</span><span class="p">))</span>
<span class="p">.</span><span class="nf">then</span><span class="p">(</span><span class="nx">data</span> <span class="o">=></span> <span class="p">{</span>
<span class="c1">// your logic</span>
<span class="p">});</span>
</code></pre>
</div>
<h4>
<code>react-native-file-access</code>
</h4>
<div class="highlight js-code-highlight">
<pre class="highlight typescript"><code><span class="k">import</span> <span class="p">{</span> <span class="nx">Platform</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">react-native</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">Dirs</span><span class="p">,</span> <span class="nx">FileSystem</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">react-native-file-access</span><span class="dl">'</span><span class="p">;</span>
<span class="k">export</span> <span class="k">async</span> <span class="kd">function</span> <span class="nf">readAsset</span><span class="p">(</span><span class="nx">name</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="nb">Promise</span><span class="o"><</span><span class="kr">string</span> <span class="o">|</span> <span class="kc">null</span><span class="o">></span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="k">if </span><span class="p">(</span><span class="nx">Platform</span><span class="p">.</span><span class="nx">OS</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">android</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">tmpPath</span> <span class="o">=</span> <span class="nx">Dirs</span><span class="p">.</span><span class="nx">CacheDir</span> <span class="o">+</span> <span class="s2">`/</span><span class="p">${</span><span class="nx">name</span><span class="p">}</span><span class="s2">`</span><span class="p">;</span>
<span class="k">await</span> <span class="nx">FileSystem</span><span class="p">.</span><span class="nf">cpAsset</span><span class="p">(</span><span class="s2">`raw/</span><span class="p">${</span><span class="nx">name</span><span class="p">}</span><span class="s2">`</span><span class="p">,</span> <span class="nx">tmpPath</span><span class="p">,</span> <span class="dl">'</span><span class="s1">resource</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">content</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">FileSystem</span><span class="p">.</span><span class="nf">readFile</span><span class="p">(</span><span class="nx">tmpPath</span><span class="p">,</span> <span class="dl">'</span><span class="s1">utf8</span><span class="dl">'</span><span class="p">);</span>
<span class="k">return</span> <span class="nx">content</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">const</span> <span class="nx">path</span> <span class="o">=</span> <span class="s2">`</span><span class="p">${</span><span class="nx">Dirs</span><span class="p">.</span><span class="nx">MainBundleDir</span><span class="p">}</span><span class="s2">/</span><span class="p">${</span><span class="nx">name</span><span class="p">}</span><span class="s2">`</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">content</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">FileSystem</span><span class="p">.</span><span class="nf">readFile</span><span class="p">(</span><span class="nx">path</span><span class="p">,</span> <span class="dl">'</span><span class="s1">utf8</span><span class="dl">'</span><span class="p">);</span>
<span class="k">return</span> <span class="nx">content</span><span class="p">;</span>
<span class="p">}</span> <span class="k">catch </span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nf">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Error reading asset:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">e</span><span class="p">);</span>
<span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Usage example</span>
<span class="nf">readAsset</span><span class="p">(</span>
<span class="nx">Platform</span><span class="p">.</span><span class="nf">select</span><span class="p">({</span>
<span class="na">ios</span><span class="p">:</span> <span class="dl">'</span><span class="s1">animation.json</span><span class="dl">'</span><span class="p">,</span>
<span class="na">android</span><span class="p">:</span> <span class="dl">'</span><span class="s1">animation</span><span class="dl">'</span><span class="p">,</span> <span class="c1">// skip extension for Android</span>
<span class="p">}),</span>
<span class="p">)</span>
<span class="p">.</span><span class="nf">then</span><span class="p">(</span><span class="nx">jsonStr</span> <span class="o">=></span> <span class="nx">JSON</span><span class="p">.</span><span class="nf">parse</span><span class="p">(</span><span class="nx">jsonStr</span><span class="p">))</span>
<span class="p">.</span><span class="nf">then</span><span class="p">(</span><span class="nx">data</span> <span class="o">=></span> <span class="p">{</span>
<span class="c1">// your logic</span>
<span class="p">});</span>
</code></pre>
</div>
<p>Now you understand how easy it is to read your asset files. From here, you can load these files at any time, which will significantly accelerate your app's start time and reduce memory consumption.</p>
<p>It's also worth mentioning that you can employ various approaches for how and when to load your assets. For instance, you might preload all necessary files at a specific initial stage. Additionally, caching the results can prevent the need to read and parse JSON multiple times.</p>
<h3>
Render lazy loaded assets
</h3>
<p>I can also share a React component example showcasing how to implement data loading using the <code>use</code> <a href="proxy.php?url=https://react.dev/reference/react/use#use" rel="noopener noreferrer">React hook</a> and <a href="proxy.php?url=https://react.dev/reference/react/Suspense" rel="noopener noreferrer">Suspense</a>:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight typescript"><code><span class="k">import</span> <span class="p">{</span> <span class="nx">readAsset</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">./my-fs.js</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">MyLottie</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">./my-lottie.js</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">Suspense</span><span class="p">,</span> <span class="nx">use</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">react</span><span class="dl">'</span><span class="p">;</span> <span class="c1">// Assuming 'use' and 'Suspense' are imported.</span>
<span class="kd">const</span> <span class="nx">sourcePromise</span> <span class="o">=</span> <span class="nf">readAsset</span><span class="p">(</span><span class="dl">'</span><span class="s1">new-chat-anim.json</span><span class="dl">'</span><span class="p">).</span><span class="nf">then</span><span class="p">(</span><span class="nx">s</span> <span class="o">=></span> <span class="nx">JSON</span><span class="p">.</span><span class="nf">parse</span><span class="p">(</span><span class="nx">s</span><span class="p">));</span>
<span class="k">export</span> <span class="k">default</span> <span class="kd">function</span> <span class="nf">App</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return </span><span class="p">(</span>
<span class="o"><</span><span class="nx">Suspense</span> <span class="nx">fallback</span><span class="o">=</span><span class="p">{</span><span class="cm">/* ... */</span><span class="p">}</span><span class="o">></span>
<span class="o"><</span><span class="nx">MyLottie</span> <span class="nx">sourcePromise</span><span class="o">=</span><span class="p">{</span><span class="nx">sourcePromise</span><span class="p">}</span> <span class="sr">/</span><span class="err">>
</span> <span class="o"><</span><span class="sr">/Suspense</span><span class="err">>
</span> <span class="p">);</span>
<span class="p">}</span>
<span class="c1">// ./my-lottie.js</span>
<span class="k">import</span> <span class="nx">LottieView</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">lottie-react-native</span><span class="dl">'</span><span class="p">;</span>
<span class="c1">// Assuming 'use' is imported from 'react' as well.</span>
<span class="k">export</span> <span class="kd">function</span> <span class="nf">MyLottie</span><span class="p">({</span> <span class="nx">sourcePromise</span> <span class="p">})</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">source</span> <span class="o">=</span> <span class="nf">use</span><span class="p">(</span><span class="nx">sourcePromise</span><span class="p">);</span>
<span class="k">return</span> <span class="o"><</span><span class="nx">LottieView</span> <span class="nx">source</span><span class="o">=</span><span class="p">{</span><span class="nx">source</span><span class="p">}</span> <span class="sr">/></span><span class="err">;
</span><span class="p">}</span>
</code></pre>
</div>
<p>As an alternative solution, you can also load data over the internet. For example, Re.Pack offers <a href="proxy.php?url=https://re-pack.dev/docs/guides/remote-assets" rel="noopener noreferrer">remote assets</a> functionality.</p>
<p>Lastly, the example involving locales JSON files will be discussed in a dedicated article, as previously detailed in <a href="proxy.php?url=https://dev.to/retyui/99-of-react-native-apps-make-this-localization-i18n-mistake-is-yours-one-of-them-2o6g">π¨ 99% of React Native Apps Make This Localization (i18n) Mistake β Is Yours One of Them?</a></p>
reactnative
react
performance
mobile
-
How to fix "ADB server didn't ACK" error on MacOS Sequoia
Davyd NRB
Wed, 27 Nov 2024 14:44:58 +0000
https://dev.to/retyui/how-to-fix-adb-server-didnt-ack-error-on-macos-sequoia-mka
https://dev.to/retyui/how-to-fix-adb-server-didnt-ack-error-on-macos-sequoia-mka
<p>If you see the next error in you stdout when you run <code>adb</code> commands, I have a simple solution for you: temporarily disable unused interfaces, such as <code>awdl0</code> (used for <strong>AirDrop</strong>) or other virtual interfaces: <code>sudo ifconfig awdl0 down</code><br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight java"><code><span class="o">*</span> <span class="n">daemon</span> <span class="n">not</span> <span class="n">running</span><span class="o">;</span> <span class="n">starting</span> <span class="n">now</span> <span class="n">at</span> <span class="nl">tcp:localhost:</span><span class="mi">5037</span>
<span class="no">ADB</span> <span class="n">server</span> <span class="n">didn</span><span class="err">'</span><span class="n">t</span> <span class="no">ACK</span>
<span class="nc">Full</span> <span class="n">server</span> <span class="n">startup</span> <span class="nl">log:</span> <span class="o">/</span><span class="kt">var</span><span class="o">/</span><span class="n">folders</span><span class="o">/</span><span class="n">f5</span><span class="o">/</span><span class="mi">3</span><span class="n">pmcz80n74n56ymms26g_4h00000gn</span><span class="o">/</span><span class="no">T</span><span class="c1">//adb.501.log</span>
<span class="nc">Server</span> <span class="n">had</span> <span class="nl">pid:</span> <span class="mi">73568</span>
<span class="o">---</span> <span class="n">adb</span> <span class="nf">starting</span> <span class="o">(</span><span class="n">pid</span> <span class="mi">73568</span><span class="o">)</span> <span class="o">---</span>
<span class="mi">11</span><span class="o">-</span><span class="mi">27</span> <span class="mi">15</span><span class="o">:</span><span class="mi">26</span><span class="o">:</span><span class="mf">43.561</span> <span class="mi">73568</span> <span class="mi">622665</span> <span class="no">I</span> <span class="n">adb</span> <span class="o">:</span> <span class="n">main</span><span class="o">.</span><span class="na">cpp</span><span class="o">:</span><span class="mi">63</span> <span class="nc">Android</span> <span class="nc">Debug</span> <span class="nc">Bridge</span> <span class="n">version</span> <span class="mf">1.0</span><span class="o">.</span><span class="mi">41</span>
<span class="mi">11</span><span class="o">-</span><span class="mi">27</span> <span class="mi">15</span><span class="o">:</span><span class="mi">26</span><span class="o">:</span><span class="mf">43.561</span> <span class="mi">73568</span> <span class="mi">622665</span> <span class="no">I</span> <span class="n">adb</span> <span class="o">:</span> <span class="n">main</span><span class="o">.</span><span class="na">cpp</span><span class="o">:</span><span class="mi">63</span> <span class="nc">Version</span> <span class="mf">35.0</span><span class="o">.</span><span class="mi">2</span><span class="o">-</span><span class="mi">12147458</span>
<span class="mi">11</span><span class="o">-</span><span class="mi">27</span> <span class="mi">15</span><span class="o">:</span><span class="mi">26</span><span class="o">:</span><span class="mf">43.561</span> <span class="mi">73568</span> <span class="mi">622665</span> <span class="no">I</span> <span class="n">adb</span> <span class="o">:</span> <span class="n">main</span><span class="o">.</span><span class="na">cpp</span><span class="o">:</span><span class="mi">63</span> <span class="nc">Installed</span> <span class="n">as</span> <span class="o">/</span><span class="nc">Users</span><span class="o">/</span><span class="n">hi</span><span class="o">/</span><span class="nc">Library</span><span class="o">/</span><span class="nc">Android</span><span class="o">/</span><span class="n">sdk</span><span class="o">/</span><span class="n">platform</span><span class="o">-</span><span class="n">tools</span><span class="o">/</span><span class="n">adb</span>
<span class="mi">11</span><span class="o">-</span><span class="mi">27</span> <span class="mi">15</span><span class="o">:</span><span class="mi">26</span><span class="o">:</span><span class="mf">43.561</span> <span class="mi">73568</span> <span class="mi">622665</span> <span class="no">I</span> <span class="n">adb</span> <span class="o">:</span> <span class="n">main</span><span class="o">.</span><span class="na">cpp</span><span class="o">:</span><span class="mi">63</span> <span class="nc">Running</span> <span class="n">on</span> <span class="nc">Darwin</span> <span class="mf">24.1</span><span class="o">.</span><span class="mi">0</span> <span class="o">(</span><span class="n">arm64</span><span class="o">)</span>
<span class="mi">11</span><span class="o">-</span><span class="mi">27</span> <span class="mi">15</span><span class="o">:</span><span class="mi">26</span><span class="o">:</span><span class="mf">43.561</span> <span class="mi">73568</span> <span class="mi">622665</span> <span class="no">I</span> <span class="n">adb</span> <span class="o">:</span> <span class="n">main</span><span class="o">.</span><span class="na">cpp</span><span class="o">:</span><span class="mi">63</span>
<span class="mi">11</span><span class="o">-</span><span class="mi">27</span> <span class="mi">15</span><span class="o">:</span><span class="mi">26</span><span class="o">:</span><span class="mf">43.564</span> <span class="mi">73568</span> <span class="mi">622665</span> <span class="no">I</span> <span class="n">adb</span> <span class="o">:</span> <span class="n">auth</span><span class="o">.</span><span class="na">cpp</span><span class="o">:</span><span class="mi">416</span> <span class="n">adb_auth_init</span><span class="o">...</span>
<span class="mi">11</span><span class="o">-</span><span class="mi">27</span> <span class="mi">15</span><span class="o">:</span><span class="mi">26</span><span class="o">:</span><span class="mf">43.566</span> <span class="mi">73568</span> <span class="mi">622665</span> <span class="no">I</span> <span class="n">adb</span> <span class="o">:</span> <span class="n">auth</span><span class="o">.</span><span class="na">cpp</span><span class="o">:</span><span class="mi">152</span> <span class="n">loaded</span> <span class="k">new</span> <span class="n">key</span> <span class="n">from</span> <span class="err">'</span><span class="o">/</span><span class="nc">Users</span><span class="o">/</span><span class="n">hi</span><span class="o">/.</span><span class="na">android</span><span class="o">/</span><span class="n">adbkey</span><span class="err">'</span> <span class="n">with</span> <span class="n">fingerprint</span> <span class="mi">0</span><span class="no">CBF619FA32DB4D1DE6D7228BFE4C2205D41C69DD69C2EB6F0EC7E9A1D43D678</span>
<span class="mi">11</span><span class="o">-</span><span class="mi">27</span> <span class="mi">15</span><span class="o">:</span><span class="mi">26</span><span class="o">:</span><span class="mf">43.567</span> <span class="mi">73568</span> <span class="mi">622665</span> <span class="no">I</span> <span class="n">adb</span> <span class="o">:</span> <span class="n">udp_socket</span><span class="o">.</span><span class="na">cpp</span><span class="o">:</span><span class="mi">170</span> <span class="nc">AdbUdpSocket</span> <span class="n">fd</span><span class="o">=</span><span class="mi">9</span>
<span class="mi">11</span><span class="o">-</span><span class="mi">27</span> <span class="mi">15</span><span class="o">:</span><span class="mi">26</span><span class="o">:</span><span class="mf">43.567</span> <span class="mi">73568</span> <span class="mi">622665</span> <span class="no">I</span> <span class="n">adb</span> <span class="o">:</span> <span class="n">udp_socket</span><span class="o">.</span><span class="na">cpp</span><span class="o">:</span><span class="mi">170</span> <span class="nc">AdbUdpSocket</span> <span class="n">fd</span><span class="o">=</span><span class="mi">10</span>
<span class="mi">11</span><span class="o">-</span><span class="mi">27</span> <span class="mi">15</span><span class="o">:</span><span class="mi">26</span><span class="o">:</span><span class="mf">43.567</span> <span class="mi">73568</span> <span class="mi">622665</span> <span class="no">I</span> <span class="n">adb</span> <span class="o">:</span> <span class="n">udp_socket</span><span class="o">.</span><span class="na">cpp</span><span class="o">:</span><span class="mi">274</span> <span class="nc">SetMulticastOutboundInterface</span> <span class="k">for</span> <span class="n">index</span><span class="o">=</span><span class="mi">14</span>
<span class="mi">11</span><span class="o">-</span><span class="mi">27</span> <span class="mi">15</span><span class="o">:</span><span class="mi">26</span><span class="o">:</span><span class="mf">43.567</span> <span class="mi">73568</span> <span class="mi">622665</span> <span class="no">I</span> <span class="n">adb</span> <span class="o">:</span> <span class="n">udp_socket</span><span class="o">.</span><span class="na">cpp</span><span class="o">:</span><span class="mi">533</span> <span class="n">bind</span> <span class="n">endpoint</span><span class="o">=</span><span class="mf">0.0</span><span class="o">.</span><span class="mf">0.0</span><span class="o">:</span><span class="mi">5353</span>
<span class="mi">11</span><span class="o">-</span><span class="mi">27</span> <span class="mi">15</span><span class="o">:</span><span class="mi">26</span><span class="o">:</span><span class="mf">43.567</span> <span class="mi">73568</span> <span class="mi">622665</span> <span class="no">I</span> <span class="n">adb</span> <span class="o">:</span> <span class="n">udp_socket</span><span class="o">.</span><span class="na">cpp</span><span class="o">:</span><span class="mi">274</span> <span class="nc">SetMulticastOutboundInterface</span> <span class="k">for</span> <span class="n">index</span><span class="o">=</span><span class="mi">14</span>
<span class="mi">11</span><span class="o">-</span><span class="mi">27</span> <span class="mi">15</span><span class="o">:</span><span class="mi">26</span><span class="o">:</span><span class="mf">43.567</span> <span class="mi">73568</span> <span class="mi">622665</span> <span class="no">I</span> <span class="n">adb</span> <span class="o">:</span> <span class="n">udp_socket</span><span class="o">.</span><span class="na">cpp</span><span class="o">:</span><span class="mi">558</span> <span class="n">bind</span> <span class="n">endpoint</span><span class="o">=[</span><span class="mo">0000</span><span class="o">:</span><span class="mo">0000</span><span class="o">:</span><span class="mo">0000</span><span class="o">:</span><span class="mo">0000</span><span class="o">:</span><span class="mo">0000</span><span class="o">:</span><span class="mo">0000</span><span class="o">:</span><span class="mo">0000</span><span class="o">:</span><span class="mo">0000</span><span class="o">]:</span><span class="mi">5353</span> <span class="n">scope_id</span><span class="o">=</span><span class="mi">0</span>
<span class="mi">11</span><span class="o">-</span><span class="mi">27</span> <span class="mi">15</span><span class="o">:</span><span class="mi">26</span><span class="o">:</span><span class="mf">43.567</span> <span class="mi">73568</span> <span class="mi">622665</span> <span class="no">I</span> <span class="n">adb</span> <span class="o">:</span> <span class="n">udp_socket</span><span class="o">.</span><span class="na">cpp</span><span class="o">:</span><span class="mi">170</span> <span class="nc">AdbUdpSocket</span> <span class="n">fd</span><span class="o">=</span><span class="mi">11</span>
<span class="mi">11</span><span class="o">-</span><span class="mi">27</span> <span class="mi">15</span><span class="o">:</span><span class="mi">26</span><span class="o">:</span><span class="mf">43.567</span> <span class="mi">73568</span> <span class="mi">622665</span> <span class="no">I</span> <span class="n">adb</span> <span class="o">:</span> <span class="n">udp_socket</span><span class="o">.</span><span class="na">cpp</span><span class="o">:</span><span class="mi">274</span> <span class="nc">SetMulticastOutboundInterface</span> <span class="k">for</span> <span class="n">index</span><span class="o">=</span><span class="mi">17</span>
<span class="mi">11</span><span class="o">-</span><span class="mi">27</span> <span class="mi">15</span><span class="o">:</span><span class="mi">26</span><span class="o">:</span><span class="mf">43.567</span> <span class="mi">73568</span> <span class="mi">622665</span> <span class="no">I</span> <span class="n">adb</span> <span class="o">:</span> <span class="n">udp_socket</span><span class="o">.</span><span class="na">cpp</span><span class="o">:</span><span class="mi">558</span> <span class="n">bind</span> <span class="n">endpoint</span><span class="o">=[</span><span class="mo">0000</span><span class="o">:</span><span class="mo">0000</span><span class="o">:</span><span class="mo">0000</span><span class="o">:</span><span class="mo">0000</span><span class="o">:</span><span class="mo">0000</span><span class="o">:</span><span class="mo">0000</span><span class="o">:</span><span class="mo">0000</span><span class="o">:</span><span class="mo">0000</span><span class="o">]:</span><span class="mi">5353</span> <span class="n">scope_id</span><span class="o">=</span><span class="mi">0</span>
<span class="mi">11</span><span class="o">-</span><span class="mi">27</span> <span class="mi">15</span><span class="o">:</span><span class="mi">26</span><span class="o">:</span><span class="mf">43.634</span> <span class="mi">73568</span> <span class="mi">622665</span> <span class="no">F</span> <span class="n">adb</span> <span class="o">:</span> <span class="n">udp_socket</span><span class="o">.</span><span class="na">cpp</span><span class="o">:</span><span class="mi">447</span> <span class="nc">Check</span> <span class="nl">failed:</span> <span class="n">static_cast</span><span class="o"><</span><span class="n">size_t</span><span class="o">>(</span><span class="n">num_bytes_sent</span><span class="o">)</span> <span class="o">==</span> <span class="n">length</span> <span class="o">(</span><span class="n">static_cast</span><span class="o"><</span><span class="n">size_t</span><span class="o">>(</span><span class="n">num_bytes_sent</span><span class="o">)=</span><span class="mi">11</span><span class="o">,</span> <span class="n">length</span><span class="o">=</span><span class="mi">45</span><span class="o">)</span>
</code></pre>
</div>
-
Profitable and guaranteed winning method in the Gold Battle of Frostpunk: Beyond the Ice mobile game
Davyd NRB
Tue, 05 Mar 2024 21:50:36 +0000
https://dev.to/retyui/profitable-and-guaranteed-winning-method-in-the-gold-battle-of-frostpunk-beyond-the-ice-mobile-game-1mn4
https://dev.to/retyui/profitable-and-guaranteed-winning-method-in-the-gold-battle-of-frostpunk-beyond-the-ice-mobile-game-1mn4
<p><strong>Gold Battle</strong> in <a href="proxy.php?url=https://play.google.com/store/apps/details?id=com.com2us.frostpunk.android.google.global.normal&hl=en_US">Frostpunk mobile game</a> is a simple bar game with the next rules: Each person gets <code>100</code> chips and can distribute these chips into <code>five groups</code>. Compare each part and the one with more chips wins. </p>
<p>How can you distribute your chips to win more? </p>
<p>Win strategy the next:</p>
<ul>
<li>1 group => 21 chips</li>
<li>2 group => 21 chips</li>
<li>3 group => 37 chips</li>
<li>4 group => 21 chips</li>
<li>5 group => 0 chips</li>
</ul>
<p><a href="proxy.php?url=https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgwyyawfn6gedt64it1n7.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgwyyawfn6gedt64it1n7.png" alt="Image description" width="800" height="369"></a></p>
<p>So you will win 4/3 games as game opponent usually distribute chips like this:</p>
<ul>
<li>20-20-20-20-20</li>
<li>0-0-33-33-34</li>
</ul>
<p><a href="proxy.php?url=https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1f3xpwulz2tuolvoucsr.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1f3xpwulz2tuolvoucsr.png" alt="Image description" width="800" height="369"></a></p>
<p><a href="proxy.php?url=https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F19s22kipibt3up8pt46d.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F19s22kipibt3up8pt46d.png" alt="Image description" width="800" height="369"></a></p>
frostpunk
-
Cheat-sheet of diseases based on people's symptoms from Frostpunk: Beyond the Ice game
Davyd NRB
Sat, 24 Feb 2024 15:37:50 +0000
https://dev.to/retyui/cheat-sheet-of-diseases-based-on-peoples-symptoms-from-frostpunk-beyond-the-ice-game-2j1n
https://dev.to/retyui/cheat-sheet-of-diseases-based-on-peoples-symptoms-from-frostpunk-beyond-the-ice-game-2j1n
<p>Examples of sickness symptoms that you may encounter in the <a href="proxy.php?url=https://play.google.com/store/apps/details?id=com.com2us.frostpunk.android.google.global.normal&hl=en_US">Frostpunk mobile game</a> are provided below.</p>
<h2>
Fatigue
</h2>
<ul>
<li>I haven't dug up my quota of Coal for the day, but I feel so exhausted... What's wrong with me?</li>
<li>My workload is really too heavy, I have to work intensely every day, I feel like my body is at its limit, I often have headaches and dizziness.</li>
<li>It's really hard for me now, but I still have to keep working, so I can only hope to finish my tasks quickly and get some rest!</li>
<li>I felt as if my body was filled with lead and each step required a lot of strength. My brain has also become so sluggish that I can barely think. I really wish I could have a good rest, but now I have to face this state of fatigue.</li>
<li>My Spots on the body. I've never had it before, it's like a cold but it's also different.</li>
<li>I felt like my body was as heavy as a mountain and I could barely move. My eyes also became very heavy.</li>
<li>Maybe it's because I've been doing so much Coal handling lately, I feel my muscles are aching all over and I can't remember things, and yesterday I even moved the Coal to the lumber store.</li>
<li>Now I really want to lie down and rest, but I haven't finished my work yet, I'm really tired!</li>
<li>I had to carry heavy loads again today and I feel physically exhausted, my arms and lower back are so sore!</li>
<li>Gosh, I feel like I've been hit by a train. My head is heavy, my eyes are ary and my body is weak. I don't really know what to do</li>
<li>I don't know if I've caught some illness, but I'm feeling tired all the time.</li>
<li>I have been working in the factory for a long time and I feel very tired and my arms and legs feel very heavy.</li>
<li>I have to carry heavy loads every day and I feel very tired and my arms and back feel very sore.</li>
<li>I work intensely in a factory and feel very weak and tired, with frequent headaches and dizziness.</li>
<li>I've been working like hell for the past few days and I feel like my body is already exhausted, my arms and feet are so sore and achy!</li>
<li>My workload is really too heavy, I have to work intensely every day, I feel like my body is at its limit, I often have headaches and dizziness.</li>
<li>Now I feel very tired and weak and cannot perform my daily tasks and need to rest and regain my strength.</li>
<li>Now I feel so weak and tired that I canβt concentrate on my tasks and need to rest for a while.</li>
<li>Iβve been feeling so tired recently, and when I sleep, I struggle to wake up. Is it because itβs so cold?</li>
<li>I hadn't slept properly for days and I felt like a walking corpse. Every part of my body is aching and my brain has become very sluggish. I wish someone could help me because I feel like I can't take care of myself anymore.</li>
</ul>
<h2>
Influenza
</h2>
<ul>
<li>I felt like a sick cat, hiding in a corner. My body is exhausted and I feel like I can't accomplish anything anymore. I find even the simplest things overwhelming.</li>
<li>Stuffy nose, didn't sleep well, just got up and feel tired to the max already.</li>
<li>I felt like my body was stripped of all energy, like a bag of air. My limbs were weak and my eyes were getting heavy. I wish I could have a good rest, but I don't know when I'll recover.</li>
<li>I don't know whether it's because it's so cold outside, but my body has been burning up recently.</li>
<li>I don't have any other problems, it's just Weakness throughout the body.</li>
<li>Yesterday, I ate snow with my food. I had to. I was starving.</li>
<li>I was coughing all last night and couldn't sleep at all and now I feel like my whole body is falling apart!</li>
<li>I woke up this morning feeling like my throat was blocked by something and now I'm really struggling!</li>
<li>My nose is stuffy and I feel dizzy. I don't know if I have some strange disease or not.</li>
<li>I felt like a pile of waste, only to be abandoned. I couldn't focus on anything and my head was nothing but chaos. I wish I could find a way to get rid of this feeling, but I don't know how to do it.</li>
</ul>
<h2>
Typhus
</h2>
<ul>
<li>I felt like my body was on fire, I was hot all over and had a red rash and felt like my whole body was on the verge of burning up.</li>
<li>I think I have a cold, headache and chills and a fever, and this rash is itchy.</li>
<li>I thought it was allergies or a skin condition at first, but then I noticed my body developed a high fever and persistent headaches, and I was so weak that I had no energy to get out of bed.</li>
<li>Yesterday before bed, I found a couple more sunburnt scars. It's easy to get sunburned in the snow, but the last couple of days, I've had a headache.</li>
<li>My Fever. I've never had it before, it's like a cold but it's also different.</li>
<li>I thought it was just a common cold at first, but then I noticed that I had red patches on my skin and my appetite had become very bad and my whole body was very weak.</li>
<li>Two days ago, I was bitten by a bug. How come there are bugs that can survive in this weather?</li>
<li>I felt like my body was being pressed by an invisible force and I had no strength to move at all. I also had a red rash and a persistent headache and felt very uncomfortable throughout.</li>
<li>I felt like my body was being attacked by a virus, there was pain everywhere and it was accompanied by high fever and nausea, it felt like my whole body was in agony, it was definitely not ordinary typhoid!</li>
<li>I felt like my body had been bitten by a thousand mosquitoes, there were painful and itchy spots everywhere, and with the high fever and headache, it felt like my whole body was going to collapse.</li>
</ul>
<h2>
Septicemia
</h2>
<ul>
<li>Pale skin, Low blood pressure, Skin spots. Your body temperature may suddenly drop.</li>
<li>Chills, Fever, Low blood pressure. Your body temperature may suddenly drop.</li>
<li>Rapid heartbeat, Fever, Chills. Your body temperature may suddenly drop.</li>
<li>Skin bruises, Low body temperature, Fever. Your body temperature may suddenly drop.</li>
<li>Fever, Skin bruises, LOW body temperature. Your body temperature may suddenly drop.</li>
<li>I feel that my heart is beating faster and I am vomiting and having diarrhoea in addition to the fever.</li>
<li>I feel like my body is starting to break down and different problems are happening in every part of my body. I feel very tired and weak and my skin has become very dry and fragile. I've also been running a fever but my body temperature is unstable. I really don't know if my body can take it anymore, but I'm still hoping to recover.</li>
<li>I felt my body deteriorating and I was shivering and sweating uncontrollably. I had redness and pain around my wounds, and bruises and rashes on other parts of my body. I had been running a high fever and had developed shortness of breath and a rapid heartbeat. I felt very sick and nauseous and could not eat or sleep properly.</li>
<li>I get chills at night and have a lot of bruises on my body... You think I'm a ghost?</li>
<li>One minute I'm hot, the next I'm cold. I'm so anxious, I can't help thinking that even we've survived, there isn't much hope...</li>
<li>Skin spots, Fever, Anxiety and restlessness. Your body temperature may suddenly drop.</li>
<li>I had redness and severe pain around my wounds and the infection had spread to other parts of my body with a rash and bruising. My body had been running a high fever and I had developed chills and headaches. I felt very weak and tired and was unable to perform my daily activities properly, which was very frustrating.</li>
<li>Maybe I drink less water, but I don't go to the bathroom often. (I noticed that the patient's face was pale)</li>
<li>Fever, Anxiety and restlessness, Reduced urine output. Your body temperature may suddenly drop.</li>
<li>I feel weak all over and find it difficult to even sit up. I was experiencing redness and pain around my wounds, and I had severe fever and even cold sweats. I was very frightened because the condition made me feel that I had no control over my body and that I was dependent on others for help.</li>
</ul>
<h2>
Migraine
</h2>
<ul>
<li>I felt a sharp pain penetrating my head that lasted for several hours. My head also felt very heavy and tired and I could not even think or concentrate properly. My vision also became blurred and the pain was often accompanied by ringing in my ears and nausea.</li>
<li>I would feel a dull pain on the side of my head, sometimes accompanied by ringing in my ears and blurred vision. The pain was so uncomfortable that I was unable to carry out even simple activities of daily life. I need to lie still and breathe deeply to get some relief.</li>
<li>I felt a constant throbbing and jerking in my head that felt very heavy and exhausting, and my vision became blurred and distorted.</li>
<li>My migraines make me feel very tired and unwell, even more so than a normal headache. I need a lot of sleep</li>
<li>Even the slightest movement of my head would make me feel even more uncomfortable. I needed to lie completely still in a darkened room to get a little relief from the symptoms. The pain made me feel very lonely and helpless.</li>
<li>I'm seeing stars... Maybe I've been working too hard in the Cookhouse.</li>
</ul>
<h2>
Diphtheria
</h2>
<ul>
<li>Low blood pressure, Swelling of the neck, Fever...</li>
<li>Low blood pressure, Fever, Fatigue...</li>
<li>I felt like I had a strong smell in my throat and I felt sick every time I breathed. I also felt very weak and tired. In the last few days, I have started to have high fevers and severe headaches which make me feel like I am going to collapse.</li>
<li>My throat had been feeling a bit uncomfortable lately, but I didn't pay much attention to it. It wasn't until one day that I suddenly noticed a white membrane in my throat, which made me very scared.</li>
<li>Swelling of the neck, Nausea, Mild sore throat...</li>
<li>Is the medicine not working? I think itβs gotten worse.</li>
<li>It felt like my throat was burning and I felt extreme pain every time I swallowed. Worst of all, I started to experience strange symptoms such as a white membrane in my throat and my tongue becoming swollen. This frightened me so much that I thought I might die.</li>
<li>They say my neck is thicker. Can you take a look, Captain? (You spot that the patientβs neck is swollen)</li>
</ul>
<h2>
Frostbite
</h2>
<ul>
<li>I noticed that my toes had become purple and they were very itchy, but scratching them made them feel worse. Sometimes it would also puff up and get stuck inside my shoes making it difficult to walk. If it is not cured, I am really afraid that my feet will become deformed and affect my normal life.</li>
<li>My fingers feel numb, like I've been bitten by tiny ants, but I can't feel anything. Sometimes it also hurts, like a prick of a needle. It was really painful to feel like this!</li>
<li>Look at my hands, they're all rotten and my hands are bleeding in my gloves.</li>
<li>My arms feel very cold, as if they were wrapped in a block of ice. There is regular numbness that makes me afraid to make a fist hard sometimes. The feeling was really unbearable and left me feeling like I had nowhere to go.</li>
<li>I repaired a building a few days ago. My muscles still ache.
My skin has become very dry and the peeling has gotten worse. Sometimes red patches would appear and itched so much that I wanted to scratch them all off.</li>
</ul>
<h2>
Leprosy
</h2>
<ul>
<li>I have always felt that my body has become stranger and stranger lately. I have noticed that my skin has become less normal, with many red patches, and I often feel numbness and some loss of feeling in my hands and feet. Such symptoms make me feel very uncomfortable and I really wish I could find a solution to this problem.</li>
<li>I initially noticed that I had red patches on my body and that my skin had become very dry and hardened. These patches became larger and larger and gradually formed raised nodules. Now my face was also affected and my whole body looked horrible.</li>
<li>I have recently noticed that my arms and legs have started to become very stiff and my movements are becoming less flexible. Sometimes there is also muscle atrophy and joint pain. This has been very difficult for me as I used to be a very active person.</li>
</ul>
<h2>
Gastroenteritis
</h2>
<ul>
<li>I don't have any other problems, it's just Vomit.</li>
<li>I am dehydrated and have had diarrhoea for two days.</li>
<li>I don't have any other problems, it's just Diarrhoea.</li>
<li>My stomach hurts so much! I keep going to the bathroom.</li>
<li>I feel as if my body has been emptied, I have no energy and no appetite. Every time I ate I felt nauseous and the pain was like a kitten jumping around in my stomach.</li>
<li>Ugh, I'm such a wuss, I start to get nervous when I feel sick. It's like a bunch of little rats jumping around in my tummy now and it makes me feel very uncomfortable. And the constant farting, isn't that embarrassing?</li>
<li>My stomach feels like it has been cut by a knife and every time I walk I feel a dull unbearable pain. I have been drinking lots of herbs and taking lots of tablets but still no improvement. I feel like I have had the most painful few days of my life.</li>
<li>Gosh, Iβve felt like Iβve been walking through hell for the past few days. The inside of my stomach kept churning like an internal turmoil. I didnβt even dare to eat anything and only dared to drink some plain water. Every time I went to the toilet it was painful, it was so unbearable.</li>
<li>My stomach felt like a knife had been sliced through it and the pain was unbearable. My stomach was churning all the time, I was nauseous and had no appetite for anything I ate.</li>
<li>I felt like my stomach was on fire and the pain was unbearable. I would also feel nauseous when I ate and my diarrhoea was non-stop. Every time I went to the toilet, it was an ordeal and I wished I could get better soon.</li>
</ul>
<h2>
Tuberculosis
</h2>
<ul>
<li>My appetite has become very poor and I feel nauseous and vomit every time I eat. And I haven't had a bowel movement for days and my stomach always feels awful inside. I really hope this symptom will go away soon.</li>
<li>Iβve been coughing for a few days, and today Iβm coughing up blood. 1-Iβm not going to die, right?</li>
<li>My chest is always stuffy, as if there is a stone pressing down on It. Every time I breathe, I feel pain and discomfort. I havenβt slept properly for days because every time I lie down I cough incessantly.</li>
<li>I feel like my body has been completely taken over by this disease. Every day I have coughing, breathlessness and chest tightness, making it impossible for me to live a normal life. I know this disease is very serious.</li>
<li>Iβve been coughing for a few days, and today Iβm coughing up blood. 1-Iβm not going to die, right?</li>
</ul>
forstpunk
cheatsheet
android
-
Maximize Speed: Enabling Apple M1 Arm64 Runner for Swift iOS Builds on GitHub Actions
Davyd NRB
Sun, 11 Feb 2024 14:54:21 +0000
https://dev.to/retyui/maximize-speed-enabling-apple-m1-arm64-runner-for-swift-ios-builds-on-github-actions-ca1
https://dev.to/retyui/maximize-speed-enabling-apple-m1-arm64-runner-for-swift-ios-builds-on-github-actions-ca1
<p>Reputed as one of the top CI/CD service providers is Github Action. Recently, support for M1 Apple chips was added.Β </p>
<p>Switching to arm64 runner will speed up your iOS builds and cost the same amount of money <strong>$0.08/min</strong>, see: Github Actions pricing: <a href="proxy.php?url=https://docs.github.com/en/billing/managing-billing-for-github-actions/about-billing-for-github-actions#per-minute-rates">https://docs.github.com/en/billing/managing-billing-for-github-actions/about-billing-for-github-actions#per-minute-rates</a></p>
<p>One crucial step is to activate <code>macos-14</code>, in you yourΒ <code>.github/workflows/<name>.yml</code><br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight diff"><code><span class="p">jobs:
</span> deploy-ios-to-test-flight:
<span class="gd">- runs-on: macos-12 # xcode 14
</span><span class="gi">+ runs-on: macos-14 # M1 and Xcode 15.0.1
</span></code></pre>
</div>
<p>System info:</p>
<p><a href="proxy.php?url=https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fksny4ckhucqce6szf205.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fksny4ckhucqce6szf205.png" width="800" height="495"></a></p>
<p>Also, here the list of all tools/software pre-installed by default: <a href="proxy.php?url=https://github.com/actions/runner-images/blob/main/images/macos/macos-14-Readme.md#xcode">https://github.com/actions/runner-images/blob/main/images/macos/macos-14-Readme.md#xcode</a></p>
githubactions
m1
ios
cicd
-
Resolve memory leaks caused by Jest with Node.js 16.x and 18.x (JavaScript heap out of memory)
Davyd NRB
Mon, 08 Jan 2024 17:37:10 +0000
https://dev.to/retyui/resolve-memory-leaks-caused-by-jest-with-nodejs-16x-and-18x-javascript-heap-out-of-memory-3md5
https://dev.to/retyui/resolve-memory-leaks-caused-by-jest-with-nodejs-16x-and-18x-javascript-heap-out-of-memory-3md5
<p>We saw memory leaks when running tests using a Jest framework after migrating to an up-to-date version of Node.js in our project. (<a href="proxy.php?url=https://github.com/jestjs/jest/issues/11956"><code>jest issues#11956</code></a></p>
<ul>
<li>v14.21.3 β
(no leaks)</li>
<li>v16.20.2 β οΈ (leaks) </li>
<li>v18.19.0 β οΈ (leaks) </li>
<li>v20.10.0 β
(no leaks)</li>
</ul>
<p>Undoubtedly a Node.js problem, it was resolved in the release <a href="proxy.php?url=https://github.com/nodejs/node/releases/tag/v20.10.0"><code>v20.10.0</code></a> </p>
<p>Therefore, adding a <code>--no-compilation-cache</code> option will fix memory leaks if you plan to use versions 16 or 18.</p>
<p>see <code>package.json</code> example:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight diff"><code>{
"scripts": {
<span class="gd">- "test": "jest"
</span><span class="gi">+ "test": "node --expose-gc --no-compilation-cache node_modules/.bin/jest"
</span> }
}
</code></pre>
</div>
-
Use Genymotion SaaS to run Maestro E2E on CI
Davyd NRB
Thu, 10 Aug 2023 18:00:01 +0000
https://dev.to/retyui/use-genymotion-saas-to-run-maestro-e2e-on-ci-14hm
https://dev.to/retyui/use-genymotion-saas-to-run-maestro-e2e-on-ci-14hm
<p><a href="proxy.php?url=https://cloud.geny.io">Genymotion</a> service privide a huge amount of Android emulators that can be used to run <a href="proxy.php?url=https://maestro.mobile.dev/">Maestro E2E tests</a>. </p>
<p>I'll try to provide you a short list of instructions in this article to help you create a workflow.</p>
<p>Let's first install <a href="proxy.php?url=https://docs.genymotion.com/gmsaas/"><code>gmsaas</code></a> cli<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight tsx"><code><span class="nx">pip3</span> <span class="nx">install</span> <span class="nx">gmsaas</span>
<span class="nx">gmsaas</span> <span class="nx">config</span> <span class="kd">set</span> <span class="nx">android</span><span class="o">-</span><span class="nx">sdk</span><span class="o">-</span><span class="nx">path</span> <span class="dl">"</span><span class="s2">$ANDROID_HOME</span><span class="dl">"</span>
</code></pre>
</div>
<p>After that, you need to sign in (<em>Obviously, you must <a href="proxy.php?url=https://cloud.geny.io/signup">signup</a> first</em>)<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight tsx"><code><span class="k">export</span> <span class="nx">GMSAAS_EMAIL</span><span class="o">=</span><span class="dl">"</span><span class="s2">[email protected]</span><span class="dl">"</span>
<span class="k">export</span> <span class="nx">GMSAAS_PASSWORD</span><span class="o">=</span><span class="dl">"</span><span class="s2">you-password</span><span class="dl">"</span>
<span class="nx">gmsaas</span> <span class="nx">auth</span> <span class="nx">login</span> <span class="nx">$GMSAAS_EMAIL</span> <span class="nx">$GMSAAS_PASSWORD</span>
</code></pre>
</div>
<p>Let's begin by starting your first Android emulator now.</p>
<p>To start Android you need to know its <code>recipes_id</code>. You can make your own or use already created recipes:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight shell"><code>gmsaas recipes list <span class="c"># print list available recipes</span>
<span class="c"># ...</span>
<span class="c"># 4c015ada-e64e-4f5d-a320-06cbf6e95648 Google Pixel 3a 10.0 1080 x 2220 dpi 420 genymotion</span>
<span class="c"># 70eaaf75-bd9a-406d-9f01-682a5d400c6e Samsung Galaxy S10 10.0 1440 x 3040 dpi 560 genymotion</span>
<span class="c"># e104f058-b291-4764-8e0d-d9ff78a41192 Custom Phone 11.0 768 x 1280 dpi 320 genymotion</span>
<span class="c"># c65db329-511a-4c2a-9761-c7259649e8c7 Custom Tablet 11.0 1536 x 2048 dpi 320 genymotion</span>
<span class="c"># 95016679-8f8d-4890-b026-e4ad889aadf1 Google Pixel 3a 11.0 1080 x 2220 dpi 420 genymotion</span>
<span class="nv">INSTANCE_UUID</span><span class="o">=</span><span class="si">$(</span>gmsaas instances start 95016679-8f8d-4890-b026-e4ad889aadf1 my_instance_name<span class="si">)</span>
</code></pre>
</div>
<p>Now, on the <a href="proxy.php?url=https://cloud.geny.io/launchpad">Virtual Devices</a> page, you should be able to see a launched instance:</p>
<p><a href="proxy.php?url=https://res.cloudinary.com/practicaldev/image/fetch/s--wgOq2d48--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lsb8jxn2yndgwth7qvfk.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://res.cloudinary.com/practicaldev/image/fetch/s--wgOq2d48--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lsb8jxn2yndgwth7qvfk.png" alt="Image description" width="800" height="341"></a></p>
<p><code>INSTANCE_UUID</code> on the screenshot above have to store UUID value of that instance, using this UUIS you can connect a running instance to ADB:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight shell"><code>gmsaas instances adbconnect <span class="nv">$INSTANCE_UUID</span>
<span class="nv">$ANDROID_HOME</span>/platform-tools/adb devices <span class="c"># check if it works</span>
<span class="c"># List of devices attached</span>
<span class="c"># localhost:34953 device</span>
</code></pre>
</div>
<p>when an instance will be connected you run Maestor e2e:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight shell"><code><span class="nv">$ANDROID_HOME</span>/platform-tools/adb <span class="nb">install </span>myApp.apk
<span class="c"># ^^^ install app</span>
<span class="nv">$HOME</span>/.maestro/bin/maestro <span class="nb">test</span> .maestro/myTest.yaml
<span class="c"># ^^^ run tests</span>
</code></pre>
</div>
<p>video demonstration:</p>
<p><iframe src="proxy.php?url=https://player.vimeo.com/video/853447374" width="710" height="399">
</iframe>
</p>
<p>Finnaly when test pass don't forget to stop instance at the end:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight shell"><code>gmsaas instances stop <span class="nt">--no-wait</span> <span class="nv">$INSTANCE_UUID</span>
</code></pre>
</div>
<blockquote>
<p>If you don't want to read the manual, <strong>just copy <a href="proxy.php?url=https://github.com/retyui/Using-GitHub-Actions-to-run-your-Maestro-Flows#genymotion-saas">Maestro and Genymotion</a> from my repository as working examples.</strong></p>
</blockquote>
<p>That also includes <strong>Github Actions</strong> configuration: <a href="proxy.php?url=https://github.com/retyui/Using-GitHub-Actions-to-run-your-Maestro-Flows/blob/main/.github/workflows/android-genymotion-cloud.yaml"><code>android-genymotion-cloud.yaml</code></a></p>
<p><a href="proxy.php?url=https://res.cloudinary.com/practicaldev/image/fetch/s--8rOALbQq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zi3e9bl9uxeol2f0bfa8.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://res.cloudinary.com/practicaldev/image/fetch/s--8rOALbQq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zi3e9bl9uxeol2f0bfa8.png" alt="Image description" width="800" height="551"></a></p>
android
e2e
cicd
maestro
-
React Native force to bundle javascript in Debug build
Davyd NRB
Sun, 30 Jul 2023 21:30:35 +0000
https://dev.to/retyui/react-native-force-to-bundle-javascript-in-debug-build-32ln
https://dev.to/retyui/react-native-force-to-bundle-javascript-in-debug-build-32ln
<p>You can use a special env. variable on iOS<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight shell"><code><span class="nv">FORCE_BUNDLING</span><span class="o">=</span>1 yarn ios
</code></pre>
</div>
<p>Source: <a href="proxy.php?url=https://github.com/facebook/react-native/blob/667d85bddada31a51bcf6e05b3b042efb93ddb78/packages/react-native/scripts/react-native-xcode.sh#L39">https://github.com/facebook/react-native/blob/667d85bddada31a51bcf6e05b3b042efb93ddb78/packages/react-native/scripts/react-native-xcode.sh#L39</a></p>
<p>For android edit your app's <code>android/app/build.gradle</code> file:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight gradle"><code><span class="c1">// React Native <= 0.70.x</span>
<span class="n">project</span><span class="o">.</span><span class="na">ext</span><span class="o">.</span><span class="na">react</span> <span class="o">=</span> <span class="o">[</span>
<span class="c1">// ...</span>
<span class="nl">bundleInDebug:</span> <span class="n">System</span><span class="o">.</span><span class="na">getenv</span><span class="o">(</span><span class="s2">"FORCE_BUNDLING"</span><span class="o">)</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">,</span>
<span class="o">]</span>
<span class="c1">// React Native >= 0.71.x</span>
<span class="n">react</span> <span class="o">{</span>
<span class="n">debuggableVariants</span> <span class="o">=</span> <span class="n">System</span><span class="o">.</span><span class="na">getenv</span><span class="o">(</span><span class="s2">"FORCE_BUNDLING"</span><span class="o">)</span> <span class="o">?</span> <span class="o">[]</span> <span class="o">:</span> <span class="o">[</span><span class="s2">"debug"</span><span class="o">]</span>
<span class="o">}</span>
</code></pre>
</div>
<p>then you can use:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight shell"><code><span class="nv">FORCE_BUNDLING</span><span class="o">=</span>1 yarn android
</code></pre>
</div>
reactnative
-
React Native fix android build error "[CXX1428] exception while building Json A problem occurred starting process"
Davyd NRB
Sun, 30 Jul 2023 17:49:55 +0000
https://dev.to/retyui/react-native-fix-android-build-error-cxx1428-exception-while-building-json-a-problem-occurred-starting-process-5e2c
https://dev.to/retyui/react-native-fix-android-build-error-cxx1428-exception-while-building-json-a-problem-occurred-starting-process-5e2c
<p>I <a href="proxy.php?url=https://reactnative.dev/docs/environment-setup" rel="noopener noreferrer">setup dev environment</a> for my new m1 laptop and faced with weird error when tryied to build React Native 0.72.x <a href="proxy.php?url=https://reactnative.dev/docs/new-architecture-app-intro" rel="noopener noreferrer">New Architecture</a> on Android:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight shell"><code><span class="o">[</span>CXX1428] exception <span class="k">while </span>building Json
A problem occurred starting process
<span class="s1">'command /Users/my/Library/Android/sdk/cmake/3.22.1/bin/cmake'</span>
</code></pre>
</div>
<ol>
<li>
<p>I was managed to fix it removing all cache:<br>
</p>
<pre class="highlight shell"><code><span class="nb">rm</span> <span class="nt">-rf</span> android/app/build/ android/app/.cxx/
./android/gradlew clean <span class="nt">-p</span> android
</code></pre>
</li>
<li><p>and reinstalling some Android SDK components:</p></li>
</ol>
<p>2.1 open <code>Android Studio</code> -> open <code>Settings</code> -> then <code>Appearance & Behavior</code> -> <code>System Settings</code> -> <code>Android SDK</code> ->choose <code>SDK Tools</code> -> enable <code>Show Package Details</code></p>
<p>2.2 And then unmark all <code>CMake</code>, <code>NDK</code>, <code>Command build tools</code> versions: </p>
<p><a href="proxy.php?url=https://media.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%2Feel5btcj7to1dvho8arm.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media.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%2Feel5btcj7to1dvho8arm.png" alt="Image description" width="800" height="576"></a></p>
<p>2.3 then <code>Apply</code></p>
<p>2.4 finally install again:</p>
<ul>
<li>
<code>latest</code> Command-line Tools</li>
<li>
<code>3.22.1</code> CMake</li>
<li>
<code>23.1.7779620</code> NDK</li>
</ul>
reactnative
android
-
Best tips & tricks for E2E Maestro with React Native
Davyd NRB
Sun, 07 May 2023 20:21:36 +0000
https://dev.to/retyui/best-tips-tricks-for-e2e-maestro-with-react-native-2kaa
https://dev.to/retyui/best-tips-tricks-for-e2e-maestro-with-react-native-2kaa
<p>A collection of practical tips and techniques that simplify your developer experience of Maestro E2E framework!</p>
<h2>
1. Installing Maestro
</h2>
<p>Let's add a new script to the <code>package.json</code> file:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight json"><code><span class="p">{</span><span class="w">
</span><span class="nl">"scripts"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"install-maestro"</span><span class="p">:</span><span class="w"> </span><span class="s2">"MAESTRO_VERSION=1.37.0 curl -Ls 'https://get.maestro.mobile.dev' | bash"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre>
</div>
<p>I define the version we now support using the environment variable <code>MAESTRO_VERSION</code>. The use of the same version by our team and CI is guaranteed.</p>
<p>docs: <a href="proxy.php?url=https://maestro.mobile.dev/getting-started/installing-maestro" rel="noopener noreferrer">https://maestro.mobile.dev/getting-started/installing-maestro</a></p>
<h2>
2. Identify the app as being run by Maestro.
</h2>
<p>When an app is run by e2e, we occasionally need to configure the behavior of the app:</p>
<ol>
<li>Disable animation / pause video;</li>
<li>Stop sending analytics;</li>
<li>Turn off React Native LogBox <code>LogBox.ignoreAllLogs()</code>.</li>
</ol>
<p>For this case you need to add <a href="proxy.php?url=https://maestro.mobile.dev/api-reference/commands/launchapp#sending-launch-arguments" rel="noopener noreferrer"><code>arguments</code></a> to a <a href="proxy.php?url=https://maestro.mobile.dev/api-reference/commands/launchapp" rel="noopener noreferrer"><code>launchApp</code></a> command<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight yaml"><code><span class="pi">-</span> <span class="na">launchApp</span><span class="pi">:</span>
<span class="na">appId</span><span class="pi">:</span> <span class="s2">"</span><span class="s">com.example.app"</span>
<span class="na">arguments</span><span class="pi">:</span>
<span class="na">isE2E</span><span class="pi">:</span> <span class="s2">"</span><span class="s">true"</span>
</code></pre>
</div>
<p>And then on JS side using <a href="proxy.php?url=https://github.com/iamolegga/react-native-launch-arguments" rel="noopener noreferrer"><code>react-native-launch-arguments</code></a> package you can access that arguments<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight tsx"><code><span class="k">import</span> <span class="p">{</span> <span class="nx">LaunchArguments</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">react-native-launch-arguments</span><span class="dl">"</span><span class="p">;</span>
<span class="nx">LaunchArguments</span><span class="p">.</span><span class="nf">value</span><span class="p">().</span><span class="nx">isE2E</span> <span class="c1">// true</span>
</code></pre>
</div>
<h2>
3. Dot env file support <code>.env</code>
</h2>
<p>You need to create <code>.env</code> file with next text:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight shell"><code><span class="nt">-e</span> <span class="nv">UNIVERSAL_USERNAME</span><span class="o">=</span>[email protected]
<span class="nt">-e</span> <span class="nv">UNIVERSAL_PASSWORD</span><span class="o">=</span>123qwe
</code></pre>
</div>
<p>After that you can use that file as argument for <code>test</code> or <code>record</code> commands:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight json"><code><span class="p">{</span><span class="w">
</span><span class="nl">"scripts"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"record"</span><span class="p">:</span><span class="w"> </span><span class="s2">"$HOME/.maestro/bin/maestro record @.env"</span><span class="w">
</span><span class="nl">"test"</span><span class="p">:</span><span class="w"> </span><span class="s2">"$HOME/.maestro/bin/maestro test @.env"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre>
</div>
<p>Additionally, you can combine various env files (<code>maestro test @.env @.env.prod</code>), in which case all variables from the most recent file will replace, extend, or reset env variables from earlier files.<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight json"><code><span class="nl">"test"</span><span class="p">:</span><span class="w"> </span><span class="s2">"$HOME/.maestro/bin/maestro test @.env"</span><span class="w">
</span><span class="nl">"test-prod"</span><span class="p">:</span><span class="w"> </span><span class="s2">"yarn test @.env.prod"</span><span class="w">
</span><span class="nl">"test-staging"</span><span class="p">:</span><span class="w"> </span><span class="s2">"yarn test @.env.staging"</span><span class="w">
</span></code></pre>
</div>
<p>Example:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight shell"><code><span class="c"># .env file:</span>
<span class="nt">-e</span> <span class="nv">BACKEND</span><span class="o">=</span>staging
<span class="nt">-e</span> <span class="nv">USERNAME</span><span class="o">=</span><span class="nb">test</span>@test.com
<span class="nt">-e</span> <span class="nv">PASSWORD</span><span class="o">=</span>123qwe
<span class="c">#-----------------</span>
<span class="c"># .env.prod</span>
<span class="nt">-e</span> <span class="nv">BACKEND</span><span class="o">=</span> <span class="c"># unset variable</span>
<span class="nt">-e</span> <span class="nv">USERNAME</span><span class="o">=</span>[email protected] <span class="c"># edit existing </span>
<span class="nt">-e</span> <span class="nv">SKIP_UNBOARDING</span><span class="o">=</span><span class="nb">true</span> <span class="c"># add a new variable </span>
</code></pre>
</div>
<p>The following values will be available in the Maestro environment:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight yaml"><code><span class="s">${BACKEND} // </span><span class="kc">null</span>
<span class="s">${USERNAME} // "[email protected]"</span>
<span class="s">${PASSWORD} // "123qwe"</span>
<span class="s">${SKIP_UNBOARDING} // "true"</span>
</code></pre>
</div>
<h2>
4. Different <code>appId</code> between platforms or environments
</h2>
<p>It's common practice to differentiate production apps from non-production (staging/beta) apps using a Bundle ID (for example: <code>com.example.myapp</code> & <code>com.example.myapp.staging</code>)<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight yaml"><code><span class="c1"># .maestro/my-test.yaml</span>
<span class="na">appId</span><span class="pi">:</span> <span class="s">${APP_ID}</span>
<span class="na">name</span><span class="pi">:</span> <span class="s">My test name</span>
<span class="nn">---</span>
<span class="pi">-</span> <span class="s">launchApp</span> <span class="c1"># used an `appId` specified above</span>
</code></pre>
</div>
<p>Then using <code>-e MY_VAR=myVal</code> you can pass <code>APP_ID</code> in each test:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight json"><code><span class="p">{</span><span class="w">
</span><span class="nl">"scripts"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"test"</span><span class="p">:</span><span class="w"> </span><span class="s2">"$HOME/.maestro/bin/maestro test"</span><span class="w">
</span><span class="nl">"test-android-staging"</span><span class="p">:</span><span class="w"> </span><span class="s2">"yarn test -e APP_ID=com.example.myapp.staging"</span><span class="w">
</span><span class="nl">"test-android-prod"</span><span class="p">:</span><span class="w"> </span><span class="s2">"yarn test -e APP_ID=com.example.myapp"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre>
</div>
<p>and finally, an example of a terminal command:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight shell"><code>yarn test-android-staging .maestro/my-test.yaml
<span class="c"># ^^^ Run test using staging app</span>
yarn test-android-prod .maestro/my-test.yaml
<span class="c"># ^^^ Run test using prod app</span>
</code></pre>
</div>
<h2>
5. Filtering tests to run using tags
</h2>
<p>You have the ability to run a particular set of tests using <a href="proxy.php?url=https://maestro.mobile.dev/cli/tags" rel="noopener noreferrer"><code>tags</code></a> in Maestro.</p>
<p>Your nightly builds, for instance, frequently verify the following crucial features:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight yaml"><code><span class="na">appId</span><span class="pi">:</span> <span class="s">com.example.myapp</span>
<span class="na">name</span><span class="pi">:</span> <span class="s">Sign-in email+password</span>
<span class="na">tags</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s2">"</span><span class="s">on:pre_release"</span>
<span class="pi">-</span> <span class="s2">"</span><span class="s">on:pull_request"</span>
<span class="pi">-</span> <span class="s2">"</span><span class="s">on:nightly_build"</span>
<span class="pi">-</span> <span class="s2">"</span><span class="s">feature:auth"</span>
<span class="pi">-</span> <span class="s2">"</span><span class="s">backend:prod"</span>
<span class="pi">-</span> <span class="s2">"</span><span class="s">backend:pre_prod"</span>
<span class="pi">-</span> <span class="s2">"</span><span class="s">backend:staging"</span>
<span class="nn">---</span>
<span class="pi">-</span> <span class="s">launchApp</span>
<span class="c1"># ...</span>
</code></pre>
</div>
<p>You can use <code>--include-tags="on:nightly_build"</code> and path to your directory with <code>yaml</code> files to run all test that include an <code>on:nightly_build</code> tag:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight json"><code><span class="p">{</span><span class="w">
</span><span class="nl">"scripts"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"test"</span><span class="p">:</span><span class="w"> </span><span class="s2">"$HOME/.maestro/bin/maestro test"</span><span class="w">
</span><span class="nl">"nightly-test"</span><span class="p">:</span><span class="w"> </span><span class="s2">"yarn test --include-tags='on:nightly_build' ./path_to_flows"</span><span class="w">
</span><span class="nl">"pr-test"</span><span class="p">:</span><span class="w"> </span><span class="s2">"yarn test --include-tags='on:pull_request' ./path_to_flows"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre>
</div>
<h2>
6. Complicated <code>waitFor</code> logic
</h2>
<p>I had the issue that Maestro couldn't wait for the appearance of the "A" or "B" elements. </p>
<p>But using a <code>repeat</code> & <code>runFlow</code> we can simulate this logic:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight yaml"><code><span class="pi">-</span> <span class="na">evalScript</span><span class="pi">:</span> <span class="s">${output.myStatus = 'unknown'}</span>
<span class="pi">-</span> <span class="na">evalScript</span><span class="pi">:</span> <span class="s">${output.attemptsCount = 0}</span>
<span class="c1"># ^^^ specify initial parameters</span>
<span class="pi">-</span> <span class="na">repeat</span><span class="pi">:</span>
<span class="na">while</span><span class="pi">:</span>
<span class="na">true</span><span class="pi">:</span> <span class="s">${output.myStatus === 'unknown'}</span>
<span class="c1"># run until the status changes</span>
<span class="na">commands</span><span class="pi">:</span>
<span class="pi">-</span> <span class="na">runFlow</span><span class="pi">:</span>
<span class="na">when</span><span class="pi">:</span>
<span class="na">visible</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Booking</span><span class="nv"> </span><span class="s">failed"</span>
<span class="na">commands</span><span class="pi">:</span>
<span class="pi">-</span> <span class="na">evalScript</span><span class="pi">:</span> <span class="s">${output.myStatus = 'error'}</span>
<span class="c1"># ^^^ first `runFlow` wait for an error case</span>
<span class="pi">-</span> <span class="na">runFlow</span><span class="pi">:</span>
<span class="na">when</span><span class="pi">:</span>
<span class="na">true</span><span class="pi">:</span> <span class="s">${output.myStatus === 'unknown'}</span>
<span class="na">commands</span><span class="pi">:</span>
<span class="pi">-</span> <span class="na">runFlow</span><span class="pi">:</span>
<span class="na">when</span><span class="pi">:</span>
<span class="na">visible</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Booking</span><span class="nv"> </span><span class="s">success"</span>
<span class="na">commands</span><span class="pi">:</span>
<span class="pi">-</span> <span class="na">evalScript</span><span class="pi">:</span> <span class="s">${output.myStatus = 'success'}</span>
<span class="c1"># ^^^ second nested `runFlow` will wait for a success case</span>
<span class="c1"># The remaining logic deals with a timeout case</span>
<span class="pi">-</span> <span class="na">runFlow</span><span class="pi">:</span>
<span class="na">when</span><span class="pi">:</span>
<span class="na">true</span><span class="pi">:</span> <span class="s">${output.attemptsCount > 10}</span> <span class="c1"># Check attempt limit </span>
<span class="na">commands</span><span class="pi">:</span>
<span class="pi">-</span> <span class="na">evalScript</span><span class="pi">:</span> <span class="s">${output.myStatus = 'timeout'}</span>
<span class="pi">-</span> <span class="na">evalScript</span><span class="pi">:</span> <span class="s">${output.attemptsCount = output.attemptsCount + 1}</span> <span class="c1"># Incerunmen an attempt counter</span>
<span class="c1"># ^^^ After that you can run any logic based on `output.myStatus`</span>
<span class="c1"># for example throw an error if status isn't `success`</span>
<span class="pi">-</span> <span class="na">assertTrue</span><span class="pi">:</span> <span class="s">${output.myStatus === 'success'}</span>
</code></pre>
</div>
<h2>
7. Useful bash commands
</h2>
<p><strong>Android Debug</strong> (required to run metro in background)<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight shell"><code>./android/gradlew assembleDebug <span class="nt">-p</span> ./android <span class="c"># build debug apk</span>
find ./android <span class="nt">-type</span> f <span class="nt">-name</span> <span class="s2">"*.apk"</span> <span class="c"># find apk file</span>
yarn start <span class="c"># run metro bundler</span>
adb reverse tcp:8081 tcp:8081 <span class="c"># open port</span>
adb <span class="nb">install</span> <span class="s2">"<path_to_apk_file>"</span> <span class="c"># `path_to_apk_file` - result of `find` command above</span>
</code></pre>
</div>
<p><strong>Android Release</strong> (bundle JS with apk)<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight shell"><code>./android/gradlew assembleRelease <span class="nt">-p</span> ./android <span class="c"># build debug apk</span>
find ./android <span class="nt">-type</span> f <span class="nt">-name</span> <span class="s2">"*.apk"</span> <span class="c"># find apk file</span>
adb <span class="nb">install</span> <span class="s2">"<path_to_apk_file>"</span> <span class="c"># `path_to_apk_file` - result of `find` command above</span>
</code></pre>
</div>
<h2>
8. Run on CI using GitHub Actions
</h2>
<p>β οΈ If you want to run Maestro test using GitHub Actions on Android <strong>you can't use default ubuntu runners</strong> as nested virtualization is disabled (that required by Android Emulator).</p>
<p>See <code>run-on: *</code> table:</p>
<div class="table-wrapper-paragraph"><table>
<thead>
<tr>
<th>Runners</th>
<th>Android</th>
<th>iOS</th>
<th>Price (min)</th>
<th>Spec</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="proxy.php?url=https://docs.github.com/en/actions/using-github-hosted-runners/using-larger-runners" rel="noopener noreferrer">large ubuntu</a></td>
<td>β
</td>
<td>β</td>
<td><a href="proxy.php?url=https://docs.github.com/en/billing/managing-billing-for-github-actions/about-billing-for-github-actions#per-minute-rates" rel="noopener noreferrer">from $0.016 to $0.256</a></td>
<td>4-64CPU 15-256GB RAM</td>
</tr>
<tr>
<td><a href="proxy.php?url=https://github.blog/2023-03-01-github-actions-introducing-faster-github-hosted-x64-macos-runners/" rel="noopener noreferrer"><code>ubuntu-*</code></a></td>
<td>β</td>
<td>β</td>
<td><a href="proxy.php?url=https://docs.github.com/en/billing/managing-billing-for-github-actions/about-billing-for-github-actions#per-minute-rates" rel="noopener noreferrer">$0.008</a></td>
<td>2CPU 7GB RAM</td>
</tr>
<tr>
<td><a href="proxy.php?url=https://buildjet.com/for-github-actions" rel="noopener noreferrer"><code>custom buildjet</code></a></td>
<td>β
</td>
<td>β</td>
<td><a href="proxy.php?url=https://buildjet.com/for-github-actions/docs/about/pricing" rel="noopener noreferrer">from $0.004 to $0.048</a></td>
<td>2-34CPU 8-64GB RAM</td>
</tr>
<tr>
<td><a href="proxy.php?url=https://github.blog/2023-03-01-github-actions-introducing-faster-github-hosted-x64-macos-runners/" rel="noopener noreferrer"><code>macos-*-xl</code></a></td>
<td>β
</td>
<td>β
</td>
<td><a href="proxy.php?url=https://docs.github.com/en/billing/managing-billing-for-github-actions/about-billing-for-github-actions#per-minute-rates" rel="noopener noreferrer">0.32$</a></td>
<td>12CPU ??GB RAM</td>
</tr>
<tr>
<td><a href="proxy.php?url=https://github.blog/2023-03-01-github-actions-introducing-faster-github-hosted-x64-macos-runners/" rel="noopener noreferrer"><code>macos-*</code></a></td>
<td>β
</td>
<td>β
</td>
<td><a href="proxy.php?url=https://docs.github.com/en/billing/managing-billing-for-github-actions/about-billing-for-github-actions#per-minute-rates" rel="noopener noreferrer">0.08$</a></td>
<td>3CPU 14GB RAM</td>
</tr>
</tbody>
</table></div>
<p>Simple Github Actions workflow <code>.github/workflows/mobile-e2e.yml</code> to run Android & iOS e2e test using Maestro:</p>
<ul>
<li>no caching</li>
<li>no versionlock (xcode,java,nodejs,cocoapods)
</li>
</ul>
<div class="highlight js-code-highlight">
<pre class="highlight yaml"><code><span class="na">name</span><span class="pi">:</span> <span class="s">Maestro E2E</span>
<span class="na">on</span><span class="pi">:</span> <span class="pi">[</span><span class="nv">push</span><span class="pi">]</span>
<span class="na">concurrency</span><span class="pi">:</span>
<span class="na">group</span><span class="pi">:</span> <span class="s">${{ github.workflow }}-${{ github.ref }}</span>
<span class="na">cancel-in-progress</span><span class="pi">:</span> <span class="kc">true</span> <span class="c1"># auto cancel prev. run</span>
<span class="na">env</span><span class="pi">:</span>
<span class="na">MAESTRO_VERSION</span><span class="pi">:</span> <span class="s">1.37.0</span>
<span class="na">ANDROID_ARCH</span><span class="pi">:</span> <span class="s">x86_64</span>
<span class="na">jobs</span><span class="pi">:</span>
<span class="na">ios_e2e</span><span class="pi">:</span>
<span class="na">name</span><span class="pi">:</span> <span class="s">iOS</span>
<span class="na">runs-on</span><span class="pi">:</span> <span class="s">macos-12</span> <span class="c1"># or macos-12-xl</span>
<span class="na">steps</span><span class="pi">:</span>
<span class="pi">-</span> <span class="na">uses</span><span class="pi">:</span> <span class="s">actions/checkout@v3</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Installing Maestro</span>
<span class="na">run</span><span class="pi">:</span> <span class="s">curl -Ls "https://get.maestro.mobile.dev" | bash</span> <span class="c1"># will use `MAESTRO_VERSION` from env</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Installing Maestro dependencies</span>
<span class="na">run</span><span class="pi">:</span> <span class="pi">|</span>
<span class="s">brew tap facebook/fb</span>
<span class="s">brew install facebook/fb/idb-companion</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Install node_modules</span>
<span class="na">run</span><span class="pi">:</span> <span class="s">yarn install --frozen-lockfile</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Install Pods</span>
<span class="na">working-directory</span><span class="pi">:</span> <span class="s">ios</span>
<span class="na">run</span><span class="pi">:</span> <span class="s">pod install</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Build app for simulator</span>
<span class="na">working-directory</span><span class="pi">:</span> <span class="s">ios</span>
<span class="na">env</span><span class="pi">:</span>
<span class="na">DERIVED_DATA_PATH</span><span class="pi">:</span> <span class="s">my_build</span>
<span class="na">run</span><span class="pi">:</span> <span class="pi">|</span>
<span class="s">xcrun xcodebuild \</span>
<span class="s">-scheme "Myapp" \</span>
<span class="s">-workspace "Myapp.xcworkspace" \</span>
<span class="s">-configuration "Release" \</span>
<span class="s">-sdk "iphonesimulator" \</span>
<span class="s">-destination "generic/platform=iOS Simulator" \</span>
<span class="s">-derivedDataPath "${{ env.DERIVED_DATA_PATH }}"</span>
<span class="s">echo "Print path to *.app file"</span>
<span class="s">find "${{ env.DERIVED_DATA_PATH }}" -type d -name "*.app"</span>
<span class="c1"># ^^^ Path to *.app file (based on derivedDataPath + working-directory):</span>
<span class="c1"># ./ios/my_build/Build/Products/Release-iphonesimulator/Myapp.app</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Run e2e tests</span>
<span class="na">env</span><span class="pi">:</span>
<span class="na">APP_PATH</span><span class="pi">:</span> <span class="s2">"</span><span class="s">./ios/my_build/Build/Products/Release-iphonesimulator/Myapp.app"</span>
<span class="c1"># ^^^ change this path to your *.app file</span>
<span class="na">run</span><span class="pi">:</span> <span class="pi">|</span>
<span class="s">echo "Launching iOS Simulator"</span>
<span class="s">xcrun simctl boot "iPhone 14 Pro"</span>
<span class="s">echo "Installing app on Simulator"</span>
<span class="s">xcrun simctl install booted "${{ env.APP_PATH }}"</span>
<span class="s">echo "Start video record"</span>
<span class="s">xcrun simctl io booted recordVideo video_record.mov & echo $! > video_record.pid</span>
<span class="s">echo "Running tests with Maestro"</span>
<span class="s">$HOME/.maestro/bin/maestro test .maestro/ --format junit</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Stop video record</span>
<span class="na">if</span><span class="pi">:</span> <span class="s">always()</span>
<span class="na">run</span><span class="pi">:</span> <span class="s">kill -SIGINT $(cat video_record.pid)</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Store video record</span>
<span class="na">if</span><span class="pi">:</span> <span class="s">always()</span>
<span class="na">uses</span><span class="pi">:</span> <span class="s">actions/upload-artifact@v3</span>
<span class="na">with</span><span class="pi">:</span>
<span class="na">name</span><span class="pi">:</span> <span class="s">e2e_ios_report</span>
<span class="na">path</span><span class="pi">:</span> <span class="pi">|</span>
<span class="s">video_record.mov</span>
<span class="s">report.xml</span>
<span class="na">android_e2e</span><span class="pi">:</span>
<span class="na">name</span><span class="pi">:</span> <span class="s">Android</span>
<span class="na">runs-on</span><span class="pi">:</span> <span class="s">macos-12</span> <span class="c1"># or buildjet-4vcpu-ubuntu-2204, ubuntu-22.04-4core, macos-12-xl</span>
<span class="na">steps</span><span class="pi">:</span>
<span class="pi">-</span> <span class="na">uses</span><span class="pi">:</span> <span class="s">actions/checkout@v3</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Installing Maestro</span>
<span class="na">run</span><span class="pi">:</span> <span class="s">curl -Ls "https://get.maestro.mobile.dev" | bash</span> <span class="c1"># will use `MAESTRO_VERSION` from env</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Install node_modules</span>
<span class="na">run</span><span class="pi">:</span> <span class="s">yarn install --frozen-lockfile</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Build apk for emulator</span>
<span class="na">working-directory</span><span class="pi">:</span> <span class="s">android</span>
<span class="na">run</span><span class="pi">:</span> <span class="pi">|</span>
<span class="s">./gradlew assembleRelease --no-daemon -PreactNativeArchitectures=${{ env.ANDROID_ARCH }}</span>
<span class="s">echo "Print path to *.apk file"</span>
<span class="s">find . -type f -name "*.apk"</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Install Maestro and run e2e tests</span>
<span class="na">uses</span><span class="pi">:</span> <span class="s">reactivecircus/android-emulator-runner@v2</span>
<span class="na">env</span><span class="pi">:</span>
<span class="na">APK_PATH</span><span class="pi">:</span> <span class="s">./android/app/build/outputs/apk/release/app-release.apk</span>
<span class="s"># ^^^ change this path to your *.apk file</span>
<span class="na">with</span><span class="pi">:</span>
<span class="na">api-level</span><span class="pi">:</span> <span class="m">33</span> <span class="c1"># Android 13</span>
<span class="na">arch</span><span class="pi">:</span> <span class="s">${{ env.ANDROID_ARCH }}</span>
<span class="na">script</span><span class="pi">:</span> <span class="pi">|</span>
<span class="s">adb install "${{ env.APK_PATH }}"</span>
<span class="s">$HOME/.maestro/bin/maestro test .maestro/ --format junit</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Store tests result</span>
<span class="na">uses</span><span class="pi">:</span> <span class="s">actions/upload-artifact@v3</span>
<span class="na">with</span><span class="pi">:</span>
<span class="na">name</span><span class="pi">:</span> <span class="s">e2e_android_report</span>
<span class="na">path</span><span class="pi">:</span> <span class="pi">|</span>
<span class="s">report.xml</span>
</code></pre>
</div>
reactnative
maestro
testing
-
Fix a pod install error "undefined method 'exist' for File:Class" React Native
Davyd NRB
Fri, 27 Jan 2023 11:30:43 +0000
https://dev.to/retyui/fix-a-pod-install-error-undefined-method-exist-for-fileclass-react-native-24ke
https://dev.to/retyui/fix-a-pod-install-error-undefined-method-exist-for-fileclass-react-native-24ke
<p>It is advised to use Brew to install the arm version of <a href="proxy.php?url=https://formulae.brew.sh/formula/cocoapods" rel="noopener noreferrer"><code>cocoapods</code></a> for Apple M1/M2 chips.<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight shell"><code>brew <span class="nb">install </span>cocoapods
pod <span class="nb">install</span> <span class="c"># fail: "undefined method 'exist' for File:Class"</span>
</code></pre>
</div>
<p>In Ruby 3.2, <a href="proxy.php?url=https://github.com/ruby/ruby/commit/bf97415c02b11a8949f715431aca9eeb6311add2" rel="noopener noreferrer">"Fill.exists" was removed</a>. <code>brew</code> will automatically install the most recent version of <code>Ruby</code> when you perform a <code>brew install cocoapods</code>, which is why you encounter this problem.</p>
<p>There are two fixes I foundβthe first is advised by the React Native team, and the second is really quick but ugly!</p>
<ol>
<li><strong><a href="proxy.php?url=https://reactnative.dev/docs/environment-setup#ruby" rel="noopener noreferrer">Make use of a Ruby version manager</a></strong></li>
</ol>
<p>1.1) In the root of your react native project, create a <code>.ruby-version</code> and <code>Gemfile</code></p>
<p><code>.ruby-version</code>:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight java"><code><span class="mf">2.7</span><span class="o">.</span><span class="mi">8</span>
</code></pre>
</div>
<p><code>Gemfile</code>:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight ruby"><code><span class="n">source</span> <span class="s1">'https://rubygems.org'</span>
<span class="c1"># You may use http://rbenv.org/ or https://rvm.io/ to install and use this version</span>
<span class="n">ruby</span> <span class="no">File</span><span class="p">.</span><span class="nf">read</span><span class="p">(</span><span class="no">File</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="n">__dir__</span><span class="p">,</span> <span class="s1">'.ruby-version'</span><span class="p">)).</span><span class="nf">strip</span>
<span class="n">gem</span> <span class="s1">'cocoapods'</span><span class="p">,</span> <span class="s1">'~> 1.13.0'</span>
</code></pre>
</div>
<p>1.2) Install the Ruby version manager<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight shell"><code>brew <span class="nb">install </span>rbenv ruby-build <span class="c"># install ruby ver. manager</span>
rbenv init <span class="c"># load rbenv in your shell</span>
<span class="c"># ^^^follow instructions after re-run terminal!!! </span>
rbenv <span class="nb">install </span>2.7.8 <span class="c"># install required Ruby version</span>
</code></pre>
</div>
<p>1.3) Preinstalling ruby gems<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight shell"><code><span class="nb">cd </span>your/rn_project/folder
rbenv <span class="nb">local</span> <span class="c"># switch to 2.7.8 ruby version</span>
bundler <span class="nb">install</span> <span class="c"># install gem deps</span>
</code></pre>
</div>
<p>Finally, execute the following command to install pods when necessary<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight shell"><code><span class="nb">cd </span>ios<span class="p">;</span> bundler <span class="nb">exec </span>pod <span class="nb">install</span>
<span class="c"># or</span>
bundler <span class="nb">exec </span>pod <span class="nb">install</span> <span class="nt">--project-directory</span><span class="o">=</span>ios
</code></pre>
</div>
<ol>
<li>
<strong>Hacky/Dirty way</strong>: Install cocoapods using an outdated version of Ruby:
</li>
</ol>
<div class="highlight js-code-highlight">
<pre class="highlight shell"><code><span class="c"># clean up</span>
brew uninstall <span class="nt">--ignore-dependencies</span> ruby <span class="nt">--force</span>
brew uninstall cocoapods <span class="nt">--force</span>
<span class="nb">sudo </span>gem uninstall cocoapods
<span class="c"># install cocoapods </span>
brew <span class="nb">install </span>[email protected]
brew <span class="nb">install </span>cocoapods <span class="nt">--ignore-dependencies</span>
<span class="nb">ln</span> <span class="nt">-s</span> /opt/homebrew/opt/[email protected] /opt/homebrew/opt/ruby
</code></pre>
</div>
c
development
npm
softwareengineering