<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Artur Linnik</title>
    <description>The latest articles on DEV Community by Artur Linnik (@ar2rworld).</description>
    <link>https://dev.to/ar2rworld</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1167214%2F26ec2e1e-826f-4382-bc5b-aee4f8fb896f.png</url>
      <title>DEV Community: Artur Linnik</title>
      <link>https://dev.to/ar2rworld</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ar2rworld"/>
    <language>en</language>
    <item>
      <title>How I Installed Ubuntu Touch (Halium) on the Xiaomi Redmi 4A (rolex) — full step-by-step (Ubuntu 22.04)</title>
      <dc:creator>Artur Linnik</dc:creator>
      <pubDate>Thu, 11 Sep 2025 18:14:33 +0000</pubDate>
      <link>https://dev.to/ar2rworld/how-i-installed-ubuntu-touch-halium-on-the-xiaomi-redmi-4a-rolex-full-step-by-step-ubuntu-3l4m</link>
      <guid>https://dev.to/ar2rworld/how-i-installed-ubuntu-touch-halium-on-the-xiaomi-redmi-4a-rolex-full-step-by-step-ubuntu-3l4m</guid>
      <description>&lt;p&gt;Short version: I installed an unofficial alpha build packaged as a TWRP ZIP (HM4A-UbuntuTouch-UNOFFCIAL-ALPHA). After fixing /data and using the TWRP installer the device boots Ubuntu Touch. On my unit mobile, Wi-Fi, calls and audio output work; camera does not. Below is a detailed, copy-pasteable guide, exact commands for Ubuntu 22.04, and a troubleshooting section covering all pitfalls I ran into.&lt;/p&gt;

&lt;p&gt;Forum post I used as primary reference: &lt;a href="https://xdaforums.com/t/ubuntu-touch-rolex-redmi4a.4058619/" rel="noopener noreferrer"&gt;https://xdaforums.com/t/ubuntu-touch-rolex-redmi4a.4058619/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Screenshot / installer image: &lt;a href="https://drive.google.com/file/d/1-1S-fLcEpH56gCvPS4CqhwrfNTa2qJVv/view?usp=drivesdk" rel="noopener noreferrer"&gt;https://drive.google.com/file/d/1-1S-fLcEpH56gCvPS4CqhwrfNTa2qJVv/view?usp=drivesdk&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1) What you need (prerequisites)
&lt;/h2&gt;

&lt;p&gt;Laptop running Ubuntu 22.04 (commands below assume this).&lt;/p&gt;

&lt;p&gt;USB cable and the Redmi 4A.&lt;/p&gt;

&lt;p&gt;Unlocked bootloader for the phone (Xiaomi requires a Mi-Account permission step). Unlocking will wipe the phone.&lt;/p&gt;

&lt;p&gt;TWRP recovery for rolex (Redmi 4A) — get the build for your device from XDA/twrp.me or the thread above.&lt;/p&gt;

&lt;p&gt;HM4A-UbuntuTouch-UNOFFCIAL-ALPHA.zip (or CI build / packaged installer). If you only have images (halium-boot.img, system.img, rootfs.img, META-INF), see the TWRP zip repack step below.&lt;/p&gt;

&lt;p&gt;On the PC: install ADB &amp;amp; Fastboot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt update
sudo apt install -y adb fastboot unzip zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Optional but recommended) keep a stock MIUI fastboot ROM for Redmi 4A ready — useful to restore partitions if things go wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  2) High-level plan (what we’ll do)
&lt;/h2&gt;

&lt;p&gt;Unlock bootloader (if not already done).&lt;/p&gt;

&lt;p&gt;Flash official TWRP for rolex.&lt;/p&gt;

&lt;p&gt;Fix /data (format if needed) so TWRP can mount it.&lt;/p&gt;

&lt;p&gt;Use TWRP to install the provided Ubuntu Touch ZIP (recommended).&lt;/p&gt;

&lt;p&gt;If ZIP is broken, either repack it correctly or manually flash images in a specific order.&lt;/p&gt;

&lt;p&gt;Post-install checks and common fixes.&lt;/p&gt;

&lt;h2&gt;
  
  
  3) Unlock bootloader (brief)
&lt;/h2&gt;

&lt;p&gt;Xiaomi requires account authorization; follow Xiaomi’s official unlock procedure. If you prefer fastboot command (older devices may accept this):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fastboot devices                # confirm device in fastboot
# either:
fastboot oem unlock
# or on newer bootloaders:
fastboot flashing unlock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Warning: unlocking wipes userdata. If you haven’t backed up, do so now.&lt;/p&gt;

&lt;h2&gt;
  
  
  4) Flash TWRP (fastboot method)
&lt;/h2&gt;

&lt;p&gt;Download twrp-rolex.img (the twrp build for rolex). Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# place twrp img in current folder
fastboot devices
fastboot flash recovery twrp-rolex.img
# IMPORTANT: boot into TWRP immediately (don't reboot normally)
fastboot boot twrp-rolex.img
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you used fastboot flash recovery, some MIUI builds will overwrite custom recovery on first boot — that’s why fastboot boot (or immediately entering recovery) is recommended.&lt;/p&gt;

&lt;h2&gt;
  
  
  5) Fix /data and prepare TWRP
&lt;/h2&gt;

&lt;p&gt;If TWRP shows errors like Could not mount /data or Failed to mount /data (Invalid argument):&lt;/p&gt;

&lt;p&gt;A — Preferred (from TWRP):&lt;/p&gt;

&lt;p&gt;In TWRP: Wipe → Format Data → type yes.&lt;/p&gt;

&lt;p&gt;This removes encryption and recreates a clean /data. This deletes internal storage content.&lt;/p&gt;

&lt;p&gt;Then: Wipe → Advanced Wipe → select Data and Cache → Repair or Change File System → Change File System → ext4 (swipe to confirm).&lt;/p&gt;

&lt;p&gt;Back to TWRP main → Mount → tick Data and Cache. Confirm they mount.&lt;/p&gt;

&lt;p&gt;B — If TWRP “invalid partition selection” or format fails:&lt;/p&gt;

&lt;p&gt;The partition table may be damaged. Recommended fix: restore userdata.img and cache.img from the official MIUI fastboot ROM:&lt;/p&gt;

&lt;p&gt;Extract stock MIUI fastboot ROM (on PC), find userdata.img and cache.img.&lt;/p&gt;

&lt;p&gt;Boot phone to fastboot and flash those:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fastboot flash userdata userdata.img
fastboot flash cache cache.img
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: fastboot format userdata sometimes fails on Xiaomi (error about block size). Use TWRP format or stock images instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  6) Try the TWRP ZIP installer (recommended)
&lt;/h2&gt;

&lt;p&gt;If you have HM4A-UbuntuTouch-UNOFFCIAL-ALPHA.zip:&lt;/p&gt;

&lt;p&gt;Copy ZIP to phone (if /data is mounted):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;adb push HM4A-UbuntuTouch-UNOFFCIAL-ALPHA.zip /sdcard/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In TWRP: Install → select the zip → Swipe to confirm.&lt;/p&gt;

&lt;p&gt;The META-INF/com/google/android/updater-script in the ZIP will extract rootfs.img into /data and set up loop mounts properly (this is why the ZIP method is preferred).&lt;/p&gt;

&lt;p&gt;When install finishes: Reboot → System (first boot can take 5–10 minutes).&lt;/p&gt;

&lt;p&gt;If TWRP complains “Invalid zip file format” (common), see section Zip is invalid / repack below.&lt;/p&gt;

&lt;h2&gt;
  
  
  7) If the ZIP method fails — manual fastboot flashing (advanced)
&lt;/h2&gt;

&lt;p&gt;Only use this if the ZIP refuses to install and you know how to recover with TWRP/stock ROM:&lt;/p&gt;

&lt;p&gt;Boot phone to fastboot.&lt;/p&gt;

&lt;p&gt;Flash kernel/boot (halium):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fastboot flash boot halium-boot.img
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Flash system (system.img may be sparse — that’s ok; fastboot handles sparse files):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fastboot flash system system.img
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do NOT necessarily flash rootfs.img with fastboot unless the port expects that. If you must:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fastboot erase userdata
fastboot flash userdata rootfs.img
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(If fastboot flash userdata fails or creates a black screen, undo and use the TWRP zip method — many ports expect rootfs copied by the installer script.)&lt;/p&gt;

&lt;p&gt;Reboot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fastboot reboot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Important: If after flashing everything you get a black screen (no logo, blank), that usually means halium-boot.img is the wrong kernel/initramfs for your device or the rootfs isn't mounted the way the kernel expects. Try the TWRP zip installer first.&lt;/p&gt;

&lt;h2&gt;
  
  
  8) How to repack the files into a proper TWRP ZIP (if original ZIP is invalid)
&lt;/h2&gt;

&lt;p&gt;If you have a folder structure (META-INF, halium-boot.img, data/system.img, data/rootfs.img) but TWRP rejects the ZIP as invalid, repack on Ubuntu:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd HM4A-UbuntuTouch-UNOFFCIAL-ALPHA   # your folder
# from inside the folder:
zip -r9 ../HM4A-UbuntuTouch-UNOFFICIAL-ALPHA-fixed.zip *
# test the zip:
unzip -t ../HM4A-UbuntuTouch-UNOFFICIAL-ALPHA-fixed.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Push the -fixed.zip to phone and flash via TWRP.&lt;/p&gt;

&lt;h2&gt;
  
  
  9) Useful ADB / Fastboot commands (logging &amp;amp; diagnostics)
&lt;/h2&gt;

&lt;p&gt;Check fastboot connection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fastboot devices
fastboot getvar all &amp;gt; fastboot_vars.txt

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When in TWRP (adb works there), pull logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;adb devices
adb shell dmesg &amp;gt; dmesg.txt
adb shell cat /proc/last_kmsg &amp;gt; last_kmsg.txt    # may not exist on all kernels
adb pull /tmp/recovery.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If TWRP can't mount /data, check it in shell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;adb shell
ls -al /data
mount | grep data

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see Invalid sparse file format at header magic during fastboot system flash, that is usually a warning — fastboot will still send sparse chunks and succeed. You can ignore the header warning if fastboot completed.&lt;/p&gt;

&lt;h2&gt;
  
  
  10) Pitfalls &amp;amp; troubleshooting (collected from my run)
&lt;/h2&gt;

&lt;p&gt;Keep this as your quick checklist.&lt;/p&gt;

&lt;p&gt;Could not mount /data / unable to find crypto footer&lt;/p&gt;

&lt;p&gt;Why: userdata was encrypted or corrupted.&lt;/p&gt;

&lt;p&gt;Fix: In TWRP Wipe → Format Data → yes, then Repair/Change FS → ext4. If that fails, restore userdata.img from stock MIUI.&lt;/p&gt;

&lt;p&gt;Invalid erase-block-size when fastboot format userdata&lt;/p&gt;

&lt;p&gt;Why: fastboot’s mke2fs parameters wrong for Xiaomi partition geometry.&lt;/p&gt;

&lt;p&gt;Fix: Use TWRP Format Data or restore userdata.img from stock fastboot ROM.&lt;br&gt;
Invalid zip file format when flashing zip in TWRP&lt;/p&gt;

&lt;p&gt;Why: zip was not packaged correctly (renamed folder or wrong compression).&lt;/p&gt;

&lt;p&gt;Fix: Repack with zip -r9 from inside the folder, test with unzip -t.&lt;/p&gt;

&lt;p&gt;error opening: '/data/dev/loop7' (not a directory) when wiping&lt;/p&gt;

&lt;p&gt;Why: leftover files from a previous loop-mounted rootfs.&lt;/p&gt;

&lt;p&gt;Fix: Format /data or delete stale files in /data (rm -rf /data/*) from TWRP terminal after formatting.&lt;/p&gt;

&lt;p&gt;Black screen / no boot logo after flashing&lt;/p&gt;

&lt;p&gt;Why A: wrong halium-boot.img (kernel/device tree mismatch).&lt;/p&gt;

&lt;p&gt;Why B: rootfs.img was installed incorrectly (fastboot vs installer script).&lt;/p&gt;

&lt;p&gt;Fix: Reflash using the TWRP ZIP installer (preferred), or re-obtain the correct halium-boot for your device. If needed, restore stock MIUI and start over.&lt;/p&gt;

&lt;p&gt;adb logcat not found / empty&lt;/p&gt;

&lt;p&gt;adb only shows up when Android or recovery (TWRP) runs adbd. If you are in fastboot mode, use fastboot commands; boot into TWRP to use adb shell and adb pull.&lt;/p&gt;

&lt;p&gt;fastboot flash system shows sparse warning&lt;/p&gt;

&lt;p&gt;Usually harmless if fastboot completes with OKAY. Confirm by checking /system content in TWRP or boot.&lt;br&gt;
Permissions / account issues unlocking bootloader&lt;/p&gt;

&lt;p&gt;Xiaomi requires an unlock authorization. Use the official Mi Unlock process; it may require a Windows tool and waiting period for some accounts.&lt;/p&gt;
&lt;h2&gt;
  
  
  11) If you want to revert to stock (MIUI)
&lt;/h2&gt;

&lt;p&gt;Use MiFlash (Windows) with the official fastboot ROM and select clean all or flash_all. That restores stock partition layout and firmware.&lt;/p&gt;
&lt;h2&gt;
  
  
  12) What works / what doesn’t (my test)
&lt;/h2&gt;

&lt;p&gt;Works: mobile (calls), Wi-Fi, voice/audio output.&lt;/p&gt;

&lt;p&gt;Broken: camera (not working).&lt;/p&gt;

&lt;p&gt;Expect other hardware (GPS, sensors) to be hit/miss depending on the build.&lt;/p&gt;
&lt;h2&gt;
  
  
  13) Quick recovery checklist (if you get stuck)
&lt;/h2&gt;

&lt;p&gt;Can you enter fastboot? If yes — you are not hard-bricked.&lt;/p&gt;

&lt;p&gt;Can you enter TWRP? If yes — pull logs (dmesg, recovery.log) and reattempt installer zip.&lt;/p&gt;

&lt;p&gt;If /data is irrecoverable: restore userdata.img from stock MIUI or use TWRP Format Data.&lt;/p&gt;

&lt;p&gt;If system doesn’t boot after correct TWRP zip install — the port itself might be unstable; try a different CI artifact or ask the port maintainer.&lt;/p&gt;
&lt;h2&gt;
  
  
  14) Appendix — sample full session (copy/paste)
&lt;/h2&gt;

&lt;p&gt;This is the sequence that worked for me (replace filenames as needed):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# (on Ubuntu 22.04)
sudo apt update
sudo apt install -y adb fastboot unzip zip

# put device into fastboot (power + vol down)
fastboot devices

# flash or boot TWRP
fastboot boot twrp-rolex.img

# in TWRP: Wipe -&amp;gt; Format Data -&amp;gt; yes
# back on PC, push installer zip (if /data mounted)
adb push HM4A-UbuntuTouch-UNOFFCIAL-ALPHA-fixed.zip /sdcard/

# in TWRP: Install -&amp;gt; select the zip -&amp;gt; swipe to flash

# after successful install:
adb shell sleep 1
fastboot reboot

# if system doesn't boot, use TWRP to collect logs:
# boot recovery, then on PC:
adb shell dmesg &amp;gt; dmesg.txt
adb pull /tmp/recovery.log

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  15) Final notes &amp;amp; disclaimers
&lt;/h2&gt;

&lt;p&gt;This entire installation journey wouldn’t have been possible without a lot of trial, error, and guidance from ChatGPT (OpenAI GPT-5, 2025).&lt;br&gt;
I leaned on ChatGPT heavily for:&lt;/p&gt;

&lt;p&gt;debugging TWRP errors (/data mount failures, sparse image warnings, loop device issues),&lt;/p&gt;

&lt;p&gt;understanding Halium’s boot sequence,&lt;/p&gt;

&lt;p&gt;repacking the installer zip correctly,&lt;/p&gt;

&lt;p&gt;fastboot and adb command sequences,&lt;/p&gt;

&lt;p&gt;and even writing the draft for this article.&lt;/p&gt;

&lt;p&gt;If you attempt this yourself, expect setbacks — but also know that with good logs, patience, and the right questions, it’s very doable.&lt;/p&gt;

&lt;p&gt;Big thanks to the original porter(s) of Ubuntu Touch for Redmi 4A, the UBports community, and ChatGPT GPT-5 for helping breathe new life into old hardware.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwjy1ouqbk945oy96zvr2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwjy1ouqbk945oy96zvr2.jpg" alt=" " width="800" height="1066"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0jqvt1dygrq3y13ln5pj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0jqvt1dygrq3y13ln5pj.jpg" alt=" " width="800" height="1066"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>xiaomi</category>
      <category>oldphone</category>
      <category>ubuntutouch</category>
      <category>ubuntu</category>
    </item>
    <item>
      <title>If your svelte application relies a lot on store notifications, you must be careful.</title>
      <dc:creator>Artur Linnik</dc:creator>
      <pubDate>Fri, 22 Sep 2023 18:41:08 +0000</pubDate>
      <link>https://dev.to/ar2rworld/if-your-svelte-application-relies-a-lot-on-store-notifications-you-must-be-careful-3ebl</link>
      <guid>https://dev.to/ar2rworld/if-your-svelte-application-relies-a-lot-on-store-notifications-you-must-be-careful-3ebl</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Svelte store does not notify subscribers on set/update events if the value of the primitive type is the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  The story
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Once upon a time&lt;/strong&gt;, the young raccoon was trying to build a "running line" or an element on the page that would print out messages to a user based on some user interactions. Therefore, the application was heavily dependent on the store's event firing system.&lt;/p&gt;

&lt;p&gt;And as any young raccoon, our raccoon assumed that if the value is set to a store, the store will notify all subscribers even if the value is the same, right? As it occurred, the raccoon was wrong.&lt;/p&gt;

&lt;p&gt;Let's try if different types will behave differently:&lt;br&gt;
Here is a &lt;code&gt;testNotifyType&lt;/code&gt; function to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;set up a store&lt;/li&gt;
&lt;li&gt;add subscriber to log updates&lt;/li&gt;
&lt;li&gt;set the value to the store&lt;/li&gt;
&lt;li&gt;update the value&lt;/li&gt;
&lt;li&gt;put object for logs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Demo &lt;a href="https://svelte.dev/repl/5723c5777e8346658772662e6228ade1?version=4.2.1"&gt;REPL&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;testNotifyType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;writable&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;logs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="na"&gt;notifiedCounter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;comment&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notifiedCounter&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`notified with: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Trying to set: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Let's try with update with: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Feel free to skip the code
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Undefined:
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;testNotifyType(undefined, undefined);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello Store!
Can I please have a notifications for every set of "undefined" with type of undefined?
notified with: undefined
Trying to set: undefined
Let's try with update with: undefined
Notified: 1 time, so: No, sorry bro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Boolean
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;testNotifyType(true, false);&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Can I please have a notifications for every set of "true" with type of boolean?
notified with: undefined
Trying to set: true
notified with: true
Let's try with update with: false
notified with: false
Notified: 3 times, so: No, sorry bro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Number
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;testNotifyType(0, 1);&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Can I please have a notifications for every set of "0" with type of number?
notified with: undefined
Trying to set: 0
notified with: 0
Let's try with update with: 1
notified with: 1
Notified: 3 times, so: No, sorry bro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  BigInt
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;testNotifyType(BigInt(2), BigInt(3));&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Can I please have a notifications for every set of "2" with type of bigint?
notified with: undefined
Trying to set: 2
notified with: 2
Let's try with update with: 3
notified with: 3
Notified: 3 times, so: No, sorry bro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  String
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;testNotifyType("a", "b");&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Can I please have a notifications for every set of "a" with type of string?
notified with: undefined
Trying to set: a
notified with: a
Let's try with update with: b
notified with: b
Notified: 3 times, so: No, sorry bro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Symbol
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;testNotifyType(Symbol("a"), Symbol("b"));&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Can I please have a notifications for every set of "Symbol(c)" with type of symbol?
notified with: undefined
Trying to set: Symbol(c)
notified with: Symbol(c)
Let's try with update with: Symbol(d)
notified with: Symbol(d)
Notified: 3 times, so: No, sorry bro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  As you can see undefined, boolean, number, bigint, string, symbol type didn't notify subscribers.
&lt;/h3&gt;

&lt;p&gt;Should we try an object?&lt;/p&gt;

&lt;h3&gt;
  
  
  Object
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;testNotifyType({}, {}, "What about object?");&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What about object?
Can I please have a notifications for every set of "[object Object]" with type of object?
notified with: undefined
Trying to set: [object Object]
notified with: [object Object]
notified with: [object Object]
Let's try with update with: [object Object]
notified with: [object Object]
notified with: [object Object]
Notified: 5 times, so: Yes!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Array?
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;testNotifyType([4, 3], [1, 2], "What about array?");&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What about array?
Can I please have a notifications for every set of "4,3" with type of object?
notified with: undefined
Trying to set: 4,3
notified with: 4,3
notified with: 4,3
Let's try with update with: 1,2
notified with: 1,2
notified with: 1,2
Notified: 5 times, so: Yes!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  And it worked!&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;As we can see above the store will notify subscribers for the same value only in case of the &lt;code&gt;object&lt;/code&gt; type, but not &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Primitive"&gt;primitive&lt;/a&gt; types.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why?
&lt;/h2&gt;

&lt;p&gt;In case you are as curious as a young raccoon to dig deeper into the &lt;a href="https://github.com/sveltejs/svelte"&gt;sveltejs/svelte repo&lt;/a&gt;, then:&lt;br&gt;
We can see &lt;a href="https://github.com/sveltejs/svelte/blob/fa89421301f949c83d9e5e34a1f6e215137cdf4c/packages/svelte/src/runtime/store/index.js#L36"&gt;writable&lt;/a&gt;&lt;br&gt;
store does &lt;strong&gt;safe_not_equal&lt;/strong&gt; check before any actions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;writable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;noop&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/** @type {import('./public.js').Unsubscriber} */&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="cm"&gt;/** @type {Set&amp;lt;import('./private.js').SubscribeInvalidateTuple&amp;lt;T&amp;gt;&amp;gt;} */&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subscribers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="cm"&gt;/** @param {T} new_value
     * @returns {void}
     */&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;new_value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;safe_not_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;new_value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;new_value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the &lt;a href="https://github.com/sveltejs/svelte/blob/fa89421301f949c83d9e5e34a1f6e215137cdf4c/packages/svelte/src/runtime/internal/utils.js#L66"&gt;code&lt;/a&gt; for the &lt;code&gt;safe_not_equal&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/** @returns {boolean} */
export function safe_not_equal(a, b) {
    return a != a ? b == b : a !== b || (a &amp;amp;&amp;amp; typeof a === 'object') || typeof a === 'function';
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Function will return true for the same values only if an &lt;code&gt;object&lt;/code&gt; or &lt;code&gt;function&lt;/code&gt; were passed.&lt;/p&gt;

&lt;p&gt;I think it does make sense now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Workaround
&lt;/h2&gt;

&lt;p&gt;For my "running line" I've wrapped the value of the stores into the object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;queueWritable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Writable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;mutexWritable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Writable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;mutex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;waitTimeWritable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Writable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Writable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And setting the value by:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mutexWritable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;mutex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  I hope you've learned something from this "article", but if you didn't, have a good day)
&lt;/h2&gt;

&lt;p&gt;Of course, a mature raccoon already knew this feature of the svelte store because raccoon reads the source code instead of documentation, but I felt like it was worth sharing, even if a single young raccoon will find it helpful.&lt;/p&gt;

&lt;p&gt;So, be careful and be smarter than our young raccoon🦝.&lt;/p&gt;

&lt;p&gt;Be safe.&lt;/p&gt;

&lt;p&gt;Try the demo &lt;a href="https://svelte.dev/repl/5723c5777e8346658772662e6228ade1?version=4.2.1"&gt;REPL&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Provoking question:
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The world, what is the matter with you?
&lt;/h3&gt;

</description>
      <category>svelte</category>
      <category>sveltekit</category>
      <category>frontend</category>
      <category>sveltestore</category>
    </item>
  </channel>
</rss>
