Skip to content

v1.4.0

Latest

Choose a tag to compare

@github-actions github-actions released this 05 Aug 04:48

Control and clarity. This release comes out of uninstall feedback: the recurring theme was not that Drowzy did the wrong thing, but that it did not say what it was doing or give people a simple way to override it. No new permissions, no telemetry, and the native chrome.tabs.discard approach is unchanged. The 1.3.8 startup catch-up sweep is untouched.

Fixed

  • "Protect audio tabs" now works in both directions. The final pre-discard recheck in suspendTab refused any audible tab regardless of the setting. Because every suspend path funnels through that function, turning the protection off had no effect anywhere: auto-suspend, Suspend Others, Suspend this tab, the context menu, the keyboard shortcut, and the startup sweep all still refused background video and music tabs. The recheck now honours settings.protectAudio. With the setting on, behaviour is byte-for-byte what it was. This was reported directly: a user could not sleep background Twitch tabs even after unchecking the box.
  • The popup no longer hides "Suspend this tab" on audible tabs. That gate existed only to paper over the bug above, and its own comment said so.
  • What's New, onboarding and the privacy page now follow the theme you picked. All three only ever honoured the OS setting and ignored the popup's light/dark toggle, so switching Drowzy to light on a dark machine left them dark. 1.4.0 opens What's New automatically on update, so this would have been the first thing every user saw. The OS preference is still the default when no explicit choice has been made.
  • The Settings shortcut no longer gets yanked back. The popup restores its scroll position after every 5-second refresh, which fought the deliberate scroll from "Open settings" if a refresh landed mid-animation.

Added

  • "Keep this tab awake". A per-tab, session-scoped hold for the case the whitelist is too blunt for: this tab, right now, not this site forever. While held, no Drowzy path sleeps the tab - not auto-suspend, not Suspend Others, not the context menu, not the shortcut, not the startup sweep. (Chrome's own Memory Saver is a separate system and can still discard tabs on its own; the hold is scoped to what Drowzy controls, and it survives such a discard.) The button is replaced by "Allow sleep" while the hold is on, so no visible control ever contradicts the badge. Held tabs show an "Awake" badge in the tab list.

    • Stored in chrome.storage.session, following the same in-flight-promise memoisation as the 1.3.8 restore and activated sets. It survives service-worker restarts and is cleared by the browser on restart, which is deliberate: a hold is a "not right now" decision, not a setting.
    • Cleared when the tab closes, and carried across the tab-id swap on onTabReplaced.
    • Releasing a hold restarts the idle clock, so a tab held past its threshold does not vanish the instant you allow it to sleep again.
  • Reasons instead of silence. "Suspend this tab" is now shown disabled with an explanation rather than quietly disappearing. Two separate uninstall notes said Drowzy had no suspend button on tabs where it had in fact been hidden.

  • A shortcut to the setting that would change it. When a tab is protected by a toggle you control (pinned, audio), the reason line offers "Open settings", which expands Settings, scrolls to that exact row and flashes it.

  • Failed suspends now say why. Clicking suspend and getting nothing back was a recurring "not working" report. The failure path now reports the actual reason (pinned, audio, whitelisted, kept awake, still loading, unsaved form input) and falls back to an honest generic message when Chrome refuses for its own reasons. The explanation is computed only after a suspend has already failed, so it costs nothing on the happy path and can never influence whether a tab is discarded.

  • Honest framing on the memory numbers. Around ten uninstalls cited "didn't notice a memory difference", and overclaiming was making that worse. "Lifetime RAM saved" now has its own tooltip stating plainly that it counts ~150 MB per tab ever slept and is a running total over time rather than memory free right now. No disclaimer paragraph was added to the panel; the tooltips carry it.

  • Site icons now come from Chrome's own favicon cache. Loading a site's favicon URL directly from an extension page is a cross-origin request with no cookies, and anything sitting behind Cloudflare answers it with a challenge instead of an image - so the icon silently failed and the tab fell back to a letter circle. This affected a whole class of sites, claude.ai among them. Drowzy now reads Chrome's local cache instead, which works for sites that refuse us, for sleeping tabs, and for extension and system pages.

    • This adds one permission, favicon. It reads a cache already on your machine, makes no network request, is not a host permission, and Chrome shows no warning for it. It is the only way to render these icons at all; the alternative was leaving them permanently broken.
  • Favicons no longer disappear into the background. Favicons are images, so unlike every icon Drowzy draws they cannot follow the theme: a black mark vanished on the dark panel and a white one vanished on the light panel. Nothing is drawn behind any icon. Instead each one is measured once against the current theme and left alone unless it would genuinely disappear:

    • A monochrome mark on transparency (GitHub's is the obvious example) is flipped to its opposite shade. Sites like these publish both a light and a dark version of the same mark and Chrome only cached one of them, so Drowzy produces the other. There is no hue to damage, so the result matches the site's own alternate asset.
    • A coloured icon that blends gets a thin outline tracing the glyph instead, because inverting it would change the brand colour. The threshold for "monochrome" is deliberately tight: a very dark navy still carries enough hue to invert into a warm cream, so it takes the outline.
    • Everything else, which is the large majority, is untouched. Switching theme re-measures them all.
    • This applies to every favicon in the UI - the tab list, the current-tab header and the stacked icons on saved session cards - and to both icon sources, Chrome's cache and the page-reported fallback used when the cache misses.
  • Sleeping tabs keep their favicon. Chrome drops tab.favIconUrl the moment a tab is discarded, so the tab list turned into a wall of anonymous letter circles the instant you hit Suspend Others - the icons disappeared exactly when the list mattered most. Drowzy now remembers the last icon it saw for each tab and serves it back when Chrome has none. The same fallback applies to saved sessions, which previously stored no icons at all if you saved while tabs were asleep.

  • Real icons for pages that never have a favicon. Extension pages used to show a letter taken from their random extension id, and chrome:// pages a letter from an internal hostname. They now get a puzzle piece, a padlock, or a document icon as appropriate.

  • 27 more icons in the shared Lucide map (57 total), all currentColor so they follow the theme.

Changed

  • No more bounce. Suspend Others re-renders every row at once, and the badges scaled up from 0.8 while the stat numbers scaled to 1.08, which read as cartoony rather than responsive. Both are plain fades now, and the session-card entrance no longer uses an overshooting easing curve.
  • Stats count tabs going to sleep, not button presses. Suspend Others followed by Wake All, in a loop, used to inflate the lifetime figures without limit - the numbers stopped meaning anything, and a large enough one overflowed the stat cards. A tab re-slept within a minute of last being counted no longer counts again; nobody legitimately wakes and re-sleeps the same tab twice inside sixty seconds, so real use is unaffected. (Spamming Suspend Others alone never inflated anything - already-discarded tabs are skipped before the counter is reached.)
  • Large numbers can no longer break the layout. Counters compact past ten thousand (15.4k, 12.3M) and the RAM figure carries on into TB instead of printing four-digit gigabytes.
  • The suspend-warning banner's button is now "Not now" (was "Keep awake"). It only ever deferred one imminent suspend by bumping the tab's idle timer; with a real open-ended hold now available under nearly the same name, the old label was actively misleading. The i18n key keepAwakeBtn is replaced by bannerNotNow.
  • What's New opens once on update to 1.4.0. The rule is still major-bump-only; 1.4.0 is a narrow, explicitly listed exception, because a release about telling people what Drowzy is doing is worth one tab.
  • Em and en dashes removed from every locale. The 1.3.7 pass cleaned the changelog and code comments but missed _locales entirely, so all 57 locales still carried them - 375 strings in total. They were not a native punctuation choice: the same dash sat in the same structural slot in every language, including Japanese, Chinese, Arabic, Hebrew and Thai, because it had been carried over from the English source. English and most locales now use a plain hyphen; Chinese and Japanese use their own comma, which is what the surrounding translations already did. This mattered beyond house style: five of the affected strings are the tab status lines this release is built around, so an English user and a German user were seeing two different styles of the same sentence.

Internal

  • New scripts/validate.js, and CI now runs it (plus node --check on every shipped file) before building a release zip, so a broken locale cannot reach the Web Store. It checks: all 57 locales parse; key parity and placeholder integrity against en; no em or en dashes in any locale; no translation left byte-identical to English; no translation far longer than English in width-constrained furniture like badges; every data-i18n* and i18n key reference resolves; no dead keys (a dead key costs 57 files); manifest __MSG_* keys; the permission list has not grown; popup and side panel element ids have not drifted; HTML tag balance; every data-icon and icon() name exists in icons.js (a missing one renders as blank space, silently); and every referenced asset exists on disk and appears in scripts/package.sh.
  • 26 new message keys across all 57 locales. The 11 best-effort locales (Amharic, Bengali, Filipino, Gujarati, Kannada, Malayalam, Marathi, Odia, Swahili, Tamil, Telugu) use machine translations flagged for a future native-speaker pass, same as 1.3.7 and 1.3.8.

Verifying this build

This zip was built by GitHub Actions from commit 49b0c2f8df4c6056f3d44845e770b15c3786ef93. You can re-run the workflow on a fork to verify the output matches.

sha256: b323de7c49cfc8351e122547a304f5d71577eaaebab586930d83880e2983ce32