Releases: Fenish/decky
Release list
Decky 0.3.6
Desktop app 0.3.6 · Deck firmware 0.1.7 (unchanged)
Installed Decky updates itself: use the updates pill in the title bar, or Settings → Updates. New installs: run the Decky-Setup installer. The deck's firmware updates from the same place, with the deck on USB.
Desktop
- Clear the notifications key once Discord is in front (d042089)
The key counted notifications until it was tapped, so reading them in
Discord left the count on the deck. Discord's RPC has no read state or
unread count to follow, but it sends no notification while its own window
is in front - and that is where they are read.
While a key has a count, the Windows helper is asked once a second whether
the window in front is Discord's ("foreground": its process, Discord,
DiscordPTB or DiscordCanary), and the count starts again when it is. The
helper is held for this under its own name, so the camera watch letting go
cannot stop it. The foreground process id comes back as an int: PowerShell's
binder refuses a uint from a static method, and every request would have
failed.
Decky 0.3.5
Desktop app 0.3.5 · Deck firmware 0.1.7 (unchanged)
Installed Decky updates itself: use the updates pill in the title bar, or Settings → Updates. New installs: run the Decky-Setup installer. The deck's firmware updates from the same place, with the deck on USB.
Desktop
- Show a firmware update while it runs, and wait for the deck to come back (7266c30)
An install holds the session queue for as long as it writes, so the
window's status check waited behind it: the window went on believing the
deck was connected, the cache reset made that look like a boot, and "Decky
is starting" outranks "Decky is updating". Right after writing, a deck
still starting was listed as a silent device within about three seconds,
and with the install's progress still set the window offered "Finish the
update" for an update that had worked.
While firmware is written, DeckSession.flashing answers status checks at
once: offline, so the progress shows. After writing, the install asks the
port for up to 20 seconds until the deck answers before it lets go, so the
rescue is offered only for a deck that never comes back. - Let Back work on the deck again, and start at Home (9e22d13)
The snake easter egg counts taps on empty keys before a press reaches its
action, and a nested page's Back key has nothing assigned - its place is
kept for Back - so every Back press on the deck was counted as a tap and
went nowhere. Five of them started snake. isBackKey keeps it out of the
count; Back in the window was never affected.
Decky now starts at Home instead of the page it was left on, and a deck
that starts again (its BOOT line, so over USB) goes back to Home too, with
Back's history cleared. A deck restarting over Wi-Fi is not noticed yet: ID
has no boot marker, and online=0 also follows a stall.
Decky 0.3.4
Desktop app 0.3.4 · Deck firmware 0.1.7 (updated)
Installed Decky updates itself: use the updates pill in the title bar, or Settings → Updates. New installs: run the Decky-Setup installer. The deck's firmware updates from the same place, with the deck on USB.
Desktop
- Play snake on the deck, five taps on an empty key (9520ce8)
The board is one 20x12 grid across the whole panel, and each key opening
shows a 4x4 corner of it, so the snake runs behind the printed ribs and
comes out the next window. Either end of a game crushes what is on screen
into tiles that fall out of their openings, coloured from the framebuffer
as it stands. A finger dragged anywhere turns it - a key press is a tile
of the board, not a direction - so KeyListener gained a raw touched(), and
the countdown spells SWIPE TO MOVE across the keys.
The deck cannot know which of its keys are empty, so the desktop counts
the taps and sends GAME snake; the window keeps the score while it lasts
and hands the keys back when it ends.
Anything that draws a key while a game runs now waits behind one
predicate, Deck::panel_free(), which replaces the loading-and-changing
test spelled out at six call sites. Live patches, wheels and page states
are still taken - only the drawing waits, and the page is drawn whole the
moment the panel comes back.
Firmware
- Play snake on the deck, five taps on an empty key (9520ce8)
The board is one 20x12 grid across the whole panel, and each key opening
shows a 4x4 corner of it, so the snake runs behind the printed ribs and
comes out the next window. Either end of a game crushes what is on screen
into tiles that fall out of their openings, coloured from the framebuffer
as it stands. A finger dragged anywhere turns it - a key press is a tile
of the board, not a direction - so KeyListener gained a raw touched(), and
the countdown spells SWIPE TO MOVE across the keys.
The deck cannot know which of its keys are empty, so the desktop counts
the taps and sends GAME snake; the window keeps the score while it lasts
and hands the keys back when it ends.
Anything that draws a key while a game runs now waits behind one
predicate, Deck::panel_free(), which replaces the loading-and-changing
test spelled out at six call sites. Live patches, wheels and page states
are still taken - only the drawing waits, and the page is drawn whole the
moment the panel comes back.
Decky 0.3.3
Desktop app 0.3.3 · Deck firmware 0.1.6 (unchanged)
Installed Decky updates itself: use the updates pill in the title bar, or Settings → Updates. New installs: run the Decky-Setup installer. The deck's firmware updates from the same place, with the deck on USB.
Desktop
- Watch a firmware update from the screen it leaves you on (eeeceb9)
Pressing Update firmware took you to a screen that said "Decky is starting"
and nothing else: the deck restarts into its bootloader, so the dashboard -
and with it Settings, where the progress bar lives - is gone for the minute
that matters. That screen now follows the install: what part is being
written, how far, and to keep the cable in.
A cable pulled mid-write leaves a deck that answers nothing, which Decky
already offers to install onto. It now says what it is: "The update did not
finish", with a button that finishes it.
The same screen stops saying the wrong things. "Looking for Decky…" and
"Loading your pages…" are gone, the word "starting" breathes instead, and
between the deck finishing its load and the camera arriving it says "Decky
is ready" - where for half a second it used to say "offline".
Decky 0.3.2
Desktop app 0.3.2 · Deck firmware 0.1.6 (unchanged)
Installed Decky updates itself: use the updates pill in the title bar, or Settings → Updates. New installs: run the Decky-Setup installer. The deck's firmware updates from the same place, with the deck on USB.
Desktop
- Start Decky with Windows, into the tray (6cbbe18)
A deck that only works once its app has been opened by hand is not much of a
deck, so an installed Decky starts with Windows - decided once, on its first
run, and remembered, so turning it off in Settings or in Windows' own
startup list stands. A start at login carries --hidden and waits in the
tray: the deck comes up and the keys work, without a window in the face of
someone who has just logged in.
Windows is asked what the setting is rather than Decky keeping one of its
own. A development build cannot offer it - it would put the path of an
Electron in node_modules into the registry - and says so under the switch. - Keep an app's password and permission on the PC, not in the profile (ac22b9c)
Switching profiles signed you out of Discord and forgot OBS's password,
because every profile kept its own copy of them. What an app is set to is
the profile's - which OBS, what was counted - but what proves who you are
was typed on this PC and belongs to it, so secrets now live once beside the
profiles and every profile uses them.
The split is thesecretflag each field already declares, so an app added
later needs nothing new. Discord's token was the odd one out, kept in a file
of its own; it moves too, while its notification count stays with the
profile. What is already saved is adopted on the first load, so nobody signs
in again. Exports are unchanged: they never carried secrets and now cannot
see them.
Decky 0.3.1
Desktop app 0.3.1 · Deck firmware 0.1.6 (updated)
Installed Decky updates itself: use the updates pill in the title bar, or Settings → Updates. New installs: run the Decky-Setup installer. The deck's firmware updates from the same place, with the deck on USB.
Firmware
- Stop the deck holding back half a megabyte the widgets need (56f2e57)
A live picture is 29 KB, but the deck would not allocate one unless 768 KB
was free and a whole page - 430 KB - lay in one piece besides. That reserve
exists so a live picture can never starve a page build; slots keep their
buffers once they have them, so once every slot has one a page asks for no
memory at all and the reserve protects nothing. Moving a key on a profile of
8 pages was enough to lose two widgets' pictures to it.
It is kept now only while a slot has yet to take its buffer, and a refusal
says what was actually left - free= and largest= - so the next one is a
number rather than a guess.
Decky 0.3.0
Desktop app 0.3.0 · Deck firmware 0.1.5 (updated)
Installed Decky updates itself: use the updates pill in the title bar, or Settings → Updates. New installs: run the Decky-Setup installer. The deck's firmware updates from the same place, with the deck on USB.
Desktop
- Keep the profiles panel still, and let it wear the theme's scrollbar (cccc15a)
Arming the bin put a warning above the list, which pushed the list down
under the pointer; it goes to the notice at the foot of the window instead,
and a row keeps its height while its name is being typed. The rule that
separated the list from the buttons hung below them, separating nothing - it
sits above them now, and in the import view under the last line of what the
profile holds, with the name field clear of it.
Scrollbars are Decky's everywhere rather than Windows' own: one rule, so a
scrolling area added later cannot arrive in the wrong colours.
The UI check walks the import view now - what a profile holds, the widgets
this Decky has retired, what its keys would run, and the name it will be
kept under - and asserts the list does not move when the bin is armed. - Name a profile as it is imported, and never keep two of the same name (eaae396)
Importing your own profile back left two called Default. The inspector now
has the name it will be kept under, filled in with the one it came with and
yours to change before you press the button; and a name another profile
already has takes a number, whatever it was asked for. - Make a hover felt, and a delete take two presses (37a37c2)
The rows in Pages and Profiles, their icon buttons, the panel close buttons,
the editor's tabs and the icon grid had no hover at all, and the dock's was
four percent of a warm white - so the pointer said nothing. They lift now,
each over 0.15s, and the bin reddens where it means it.
Deleting a profile takes two presses: the bin arms, a tick confirms, and it
disarms itself after four seconds. While it is armed the panel says what
goes with it - the scripts the profile brought. - Let Windows open a .deckyprofile with Decky, and keep it that way (e55ea0e)
The installer registers the file type, but nothing kept it right afterwards:
an in-app update, a Decky that moved, or a copy run from elsewhere would
leave it pointing at where Decky used to be. A packaged Decky now writes the
four HKCU\Software\Classes keys on start, and only the ones that do not
already point at itself - no administrator, and nothing written when it is
already right.
The icon comes from the branding through build-icons.mjs, which now builds
both icons in one pass, and ships unpacked: inside the asar Windows could
never have read it. - Keep several profiles, and carry one whole in a .deckyprofile (6aa1d09)
Each profile is a folder of its own under profiles/ - its pages, what its
widgets counted, and the apps it talks to - with the one setup an older
Decky kept adopted as the first. What belongs to the deck rather than a
setup, its pairing and its firmware, stays where it was, so switching never
unpairs anything. Switching reloads what a profile owns in place and lets
the deck start a fresh session, so two profiles' pages never sit in its
memory at once.
A .deckyprofile carries a whole setup: its pages, the apps' settings without
their passwords, and the scripts its keys run, gzipped and encrypted with a
key Decky carries - which keeps the file out of a text editor rather than
out of anyone's hands, and says so where it matters. Importing adds a
profile, never replaces the one in use: the files land in that profile's own
folder and its keys are rewritten to point there.
Nothing is written before it is seen. One inspector serves both importing a
file and switching to a profile of your own: its pages, its widgets - the
ones this Decky no longer has named and counted - and every program and
script a key would run, which is the part worth reading in someone else's
profile. - Have each kind of action and widget say what files it keeps (c4f46c5)
An exported profile has to carry the scripts its keys run, and a list of
what to carry would be wrong the first time someone added a kind and forgot.
Instead every kind says for itself, beside where it is already declared:
ACTION_FILES gives the paths in an action and the action with them moved,
and whether the file travels at all - a script does, a program is wherever
it is installed. WIDGET_FILES does the same for widgets, which keep none
today.
Both are mapped over every kind, so a new action or widget does not compile
until it has an answer. - Give the page you are looking at the deck's last room for a live picture (28deffb)
The widget keys that kept going blank were the deck running out of PSRAM:
ERR live memory, forty times in deck.log, from the moment a microphone key
was added to a profile of 8 pages and 25 widgets. A key picture is ~29 KB,
butlive_room()asks for the 768 KB floor plus a whole page in one piece
before it will allocate one, so live pictures stop long before memory is
full - and the app, told nothing it could act on, kept sending.
The firmware now takes the live pictures of the oldest page copy that is not
on screen rather than refusing, and the desktop does the same from its side
onERR live memory, leaving hidden pages alone for a minute afterwards.
Neither needs the other: the deck's own eviction shows up as a base-CRC
mismatch, which already sends the whole key again. - Add a speed test key, over Speedtest.net's own servers (cddc48e)
Tap it and it measures the line: their config for where you are, their
server list for what is near, the five nearest pinged and the quickest kept,
then ten seconds down and ten seconds up. Tap again to stop. It ends on both
speeds with the ping, and rests there until it is tapped again.
While it hunts for a server the key is a ring the deck turns itself; while
it measures it is a dial like the volume's, following the speed on a
logarithmic scale and eased towards each reading, with the megabits in the
middle.
Decky's own client for their published endpoints, not Ookla's code or
binary: speedtest-net@1 is 2019-era with old transitive dependencies, and
its v2 downloads a CLI that does not survive packaging. Bytes are counted as
they stream over six connections down and four up, the first 1.5 s dropped
for slow start, so no correction factor is needed.
Their mirrors are asked in their own client's order, c.speedtest.net first:
the www ones hand out a short list of whatever, and a run from Istanbul
picked Liechtenstein at 46 ms. With c. first the same line finds Istanbul at
7 ms. A server that answers a ping but serves nothing is dropped for the
next best, and a dropped connection costs that stream its file, not the run. - Let a key's icon size be set back to 100% (24a2577)
The size slider means "no setting" by 100%, so it hands the editor an
appearance with no iconSize at all - and the key editor merged that with the
key it had, where a field left out cannot win. The size sprang back to what
it was, and the next step over 100 skipped it: 95, then 105.
Appearance fields are now replaced together (withAppearance), so leaving one
out takes it away, as removing an image already did by hand. The UI check
fails if the slider ever springs back off 100. - Say in deck.log why a widget key's picture is not reaching the deck (2b8c4b4)
A key that stops showing what it should leaves no trace today: the send is
refused, skipped as unchanged, or never made, and all three look the same
from outside. Each page load now logs the copy it made, and a widget key
logs what became of its pictures - at most a line every ten seconds, or a
minute for one that keeps drawing the picture the deck is thought to hold -
until it is sending again.
Also replays the reported case in a test: a key edited on a page of live
widgets, and a widget key added afterwards, both keep their pictures on the
deck. It passes, so whatever is wrong is not in this path. - Drop the icon/text spacing setting (1f5a3a7)
The gap between a key's icon and its label is now what the setting's
default gave (a fifteenth of the key), so nothing looks different; the
slider, the saved labelGap and its validation are gone. Old profiles that
carry one still load: the field is simply left behind. - Pick a widget's design on the key itself (2a1d931)
A hold on a clock, a die or a level offers the looks it can take, the way
Discord's microphone key offers its devices: the key draws each design over
a dot for each, a tap moves to the next, and three quiet seconds keep the
one showing in the profile.
Each kind names its designs, so a new one needs nothing more. Dice held to
roll, which a tap already did, so its hold is free for this; and the deck
stops turning a key while a design is picked, so the preview shows. - Keep a key's picture in the middle when it has a label (292b5e7)
A label used to move what the key shows: the icon and the label were
centred together, so the icon rode up, and a widget's caption pushed the
widget down the key. Now the label sits at the foot of the key and the
icon stays in the middle, shrinking only as far as the label and the
spacing under it need; a widget's caption leaves as much room at the
foot as it takes at the top, so the widget is a little smaller and stays
where it was. - Notice a deck that went, instead of waiting on a link that is gone (59d1e57)
A cable pulled and plugged back in while Decky was loading left it looking
connected: the unplug had fallen back to Wi-Fi, the replug took the deck's
power, and a write to a peer that is gone waits on TCP's own timeouts -
minutes - with every deck command queued behind it, the ping that would
have noticed included. Meanwhile the deck came back from its card with ...
Decky 0.2.5
Desktop app 0.2.5 · Deck firmware 0.1.4 (updated)
Installed Decky updates itself: use the updates pill in the title bar, or Settings → Updates. New installs: run the Decky-Setup installer. The deck's firmware updates from the same place, with the deck on USB.
Desktop
- Open pages with one command when the deck already has them (275ddac)
Opening a page took a round trip for CACHE, one more per toggle key to
check its ON artwork, and one for STATE - four for a page with two
toggles, which made going back to Home noticeably slower over Wi-Fi.
The app now remembers which pages and ON artwork it has confirmed on the
deck this session and opens those with STATE alone. If the deck has
dropped the page since, STATE is refused and the full exchange runs. - Show the plain firmware version after an install (82ff3dd)
The install message said "Firmware 0.1.3-1-gf30ec46-dirty installed" for
a locally built firmware; it now says 0.1.3, like the rest of the app. - Set up a deck without Decky in one step, and find it sooner (71a3ccc)
A board still on other firmware used to take four steps: "Check device",
a confirmation, the check, then "Install". The card now asks "Install
Decky on this device?" straight away; its one button checks that it is
a CrowPanel and installs, and leaves anything else untouched. It still
waits for the click, because the check restarts the device - and other
hardware on the same USB chip, like a 3D printer, must not restart.
The card also appears sooner: a silent port is asked again a second
later within the same check, and a newly plugged-in port triggers a
check at once instead of at the next four-second poll. "Looking for
Decky" hides while the card is up.
Firmware
- Keep the deck's picture from slipping, and redraw pages faster (bc9bac9)
The picture could sit 48 lines too high, wrapped, until a reset: after
power-up, a first install or Wi-Fi activity. Flash writes and Wi-Fi
calibration hold the display driver's interrupts off, two of them merge
into one, and the parity the driver uses to pick which bounce buffer to
refill flips for good - built with RESTART_IN_VSYNC, the driver never
resets it. The deck now resets it every frame, so a flip lasts one
frame. On the deck, random flash stalls left the picture slipped within
two tries before; after, 40 stalls, 75 corrections, never slipped. The
old realign after Wi-Fi and warm-up never cured it and is gone.
A page redraw took 83 ms. Keys are now copied a row at a time instead of
a pixel at a time, and drawn as soon as their row is clear of the
scanout instead of in index order: 35 ms. DISPLAY_STATE reports the
scanout bookkeeping and the last redraw time.
Decky 0.2.4
Desktop app 0.2.4 · Deck firmware 0.1.3 (updated)
Installed Decky updates itself: use the updates pill in the title bar, or Settings → Updates. New installs: run the Decky-Setup installer. The deck's firmware updates from the same place, with the deck on USB.
Desktop
- Download only what changed when Decky updates (fdfe234)
Updates are differential: releases carry the installer's blockmap, and
Decky fetches only the blocks that differ from the installed version.
Measured between two builds, an app update took 3.2 MB instead of the
full 101 MB. If anything is missing, the whole installer downloads as
before. Updates from 0.2.3 and older stay full downloads once more. - Check that every built file reaches the installer (d57b7c6)
scripts/package-check.mjs compares the build output with the packed
app.asar and fails when something is missing - the 3D model went
missing that way. pnpm dist and pnpm package run it after packaging. - Slim the installer (b0fe1aa)
The installer drops from 116 MB to 106 MB, and the installed app from
383 MB to 330 MB, while now also carrying the 3D model. Chromium ships
in English only, serialport keeps only its Windows x64 binary, source
maps and build-only files stay out, and esptool-js, already bundled
into the app, no longer ships a second copy. The two backgrounds are
lossless WebP: the same pixels, about 40% smaller. - Ship the deck model as a GLB: the installed app had none (65a14be)
electron-builder leaves every *.obj file out of the package, so the
installed Decky never had its 3D model and the Disconnected page fell
back to a still image. The model is now a GLB made from the CAD export
by scripts/convert-model.mjs: the same vertices bit for bit, 1.4 MB
instead of 6.3 MB, and it renders exactly as before. - Say Decky is offline on the Disconnected page (ad7b977)
The page now reads "Decky is offline", says how to reconnect (a USB data
cable, or power for Wi-Fi) and shows that it is looking for the deck. - Show the download speed on the update screen (4d6d494)
The update screen reads "42% · 42.0 of 99.2 MB · 12.3 MB/s", so a slow
update shows at a glance whether the network is to blame. - Show Updating on the deck while Decky updates itself (e452f95)
The deck shows the logo, "Updating Decky" and the download's progress
while the app updates, and keeps showing it through the restart for the
installer until the new version connects. Firmware without the command
ignores it.
Firmware
- Show Updating on the deck while Decky updates itself (e452f95)
The deck shows the logo, "Updating Decky" and the download's progress
while the app updates, and keeps showing it through the restart for the
installer until the new version connects. Firmware without the command
ignores it. - Stamp the firmware version in a header, not a compiler flag (d05c57a)
A new version used to recompile all 194 files, because the version was
a global define. It now goes into a generated header that only main.cpp
includes: a new version rebuilds one file, 17 s instead of 58 s.
Decky 0.2.3
Desktop app 0.2.3 · Deck firmware 0.1.2 (updated)
Installed Decky updates itself: use the updates pill in the title bar, or Settings → Updates. New installs: run the Decky-Setup installer. The deck's firmware updates from the same place, with the deck on USB.
Desktop
- Show versions as plain numbers (37deedf)
Updates shows 0.1.1 rather than v0.1.1-6-g7074263-dirty, drops the
protocol number, and no longer says the firmware is up to date when
there is simply nothing to update.
Firmware
- Fix the shifted display and boot into Disconnected (47fa9d1)
The picture could come up shifted and wrapped at power-up and stay that
way until a reset. Realigning did nothing: with RESTART_IN_VSYNC set in
this framework, esp_lcd_rgb_panel_restart() is a no-op. Realigning now
re-runs the RGB driver's full start, keeping the picture, once Wi-Fi
activity settles, after the desktop's warm-up and on DISPLAY_RESYNC.
The deck also starts on the Disconnected screen; the progress bar waits
until a desktop says HELLO.