diff --git a/.gitea/workflows/quality.yml b/.gitea/workflows/quality.yml
index 5feda5d..1bf2516 100644
--- a/.gitea/workflows/quality.yml
+++ b/.gitea/workflows/quality.yml
@@ -45,6 +45,11 @@ jobs:
assert m.get('name'), 'Chrome: Name fehlt'
assert m.get('version'), 'Chrome: Version fehlt'
assert 'storage' in m.get('permissions', []), 'Chrome: Storage Permission fehlt'
+ assert 'activeTab' in m.get('permissions', []), 'Chrome: activeTab Permission fehlt (Quick Save v2.3)'
+ assert 'background' in m, 'Chrome: background-Key fehlt (Service Worker v2.3)'
+ assert 'service_worker' in m.get('background', {}), 'Chrome: background.service_worker fehlt'
+ assert isinstance(m.get('commands'), dict) and 'quick-save' in m['commands'], 'Chrome: commands.quick-save fehlt (Quick Save v2.3)'
+ assert 'action' in m, 'Chrome: action-Key fehlt (Badge-Bestätigung v2.3)'
print('manifest.json (V3) OK — Version:', m['version'])
with open('manifest.firefox.json') as f:
@@ -52,6 +57,11 @@ jobs:
assert mf.get('manifest_version') == 3, 'Firefox: Manifest V3 erwartet'
assert mf['version'] == m['version'], 'Firefox: Version stimmt nicht mit Chrome überein!'
assert 'browser_specific_settings' in mf, 'Firefox: browser_specific_settings fehlt'
+ assert 'activeTab' in mf.get('permissions', []), 'Firefox: activeTab Permission fehlt (Quick Save v2.3)'
+ assert 'background' in mf, 'Firefox: background-Key fehlt (Event-Page v2.3)'
+ assert 'scripts' in mf.get('background', {}), 'Firefox: background.scripts fehlt (Event-Page, kein service_worker)'
+ assert isinstance(mf.get('commands'), dict) and 'quick-save' in mf['commands'], 'Firefox: commands.quick-save fehlt (Quick Save v2.3)'
+ assert 'action' in mf, 'Firefox: action-Key fehlt (Badge-Bestätigung v2.3)'
print('manifest.firefox.json (V3) OK — Version:', mf['version'])
with open('manifest.opera.json') as f:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a3fdf2b..c21355d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,20 @@ All notable changes per version. Format based on [Keep a Changelog](https://keep
---
+## [2.3.0] — 2026-06-14
+
+### Added
+- **Command Palette (Ctrl+K)** — Overlay that live-filters bookmarks (title and URL) and board names from the keyboard. Arrow-key navigation, Enter opens the match, Escape closes. Read-only navigation, separate from the web search bar. Combobox/listbox ARIA pattern with focus trap and focus return. New DE/EN i18n strings.
+- **Trash** — Deleted bookmarks and boards move to a 30-day trash instead of vanishing. Restore or permanently remove them from a new Settings section; entries older than 30 days are cleaned up automatically. Stored under its own storage key with a hard size cap so it cannot exhaust the storage quota.
+- **Quick Save** — A global keyboard shortcut (default Alt+Shift+S, configurable in the browser shortcut settings) saves the current tab into a fixed Inbox board from any page. Backed by a background worker (service worker on Chrome/Opera, event page on Firefox) that appends to a dedicated pending queue, which the dashboard drains into the Inbox — separate write domains, so a save can never clobber the boards. A badge confirms the save, and open dashboard tabs sync the new bookmark live via a storage-change listener.
+- **Free layout (bonus)** — Boards can be dragged to free positions via a drag handle, persisted per board. Positions are clamped back into view when the window shrinks, and the layout falls back to a stacked column on small screens. Each board can be pinned with a lock button: a locked board cannot be moved (its drag handle is hidden), preventing accidental repositioning. A drag only counts past a small movement threshold, so a mere click on the handle never shifts a board.
+
+### Changed
+- The bookmark- and board-delete paths no longer remove entries immediately; deletions now route through the trash.
+- Chrome and Firefox manifests gain a background worker, an `action` entry and the `activeTab` / `commands` permissions to support Quick Save. Opera keeps its existing `tabs` permission and redirect worker.
+
+---
+
## [2.2.0] — 2026-06-13
### Added
diff --git a/_locales/de/messages.json b/_locales/de/messages.json
index 9488c5d..5039da3 100644
--- a/_locales/de/messages.json
+++ b/_locales/de/messages.json
@@ -1,4 +1,8 @@
{
"extName": { "message": "Hellion NewTab" },
- "extDesc": { "message": "Persönliches Bookmark-Dashboard mit Boards, Widgets und 11 Themes. Komplett lokal, keine Cloud, kein Tracking." }
+ "extDesc": { "message": "Persönliches Bookmark-Dashboard mit Boards, Widgets und 11 Themes. Komplett lokal, keine Cloud, kein Tracking." },
+ "cmdQuickSave": { "message": "Aktuellen Tab in die Inbox speichern" },
+ "quickSaveBadge": { "message": "OK" },
+ "quickSaveSaved": { "message": "Gespeichert" },
+ "quickSaveNoTab": { "message": "Kein Tab" }
}
diff --git a/_locales/en/messages.json b/_locales/en/messages.json
index 05b192a..fc44753 100644
--- a/_locales/en/messages.json
+++ b/_locales/en/messages.json
@@ -1,4 +1,8 @@
{
"extName": { "message": "Hellion NewTab" },
- "extDesc": { "message": "Personal bookmark dashboard with boards, widgets, and 11 themes. Local-only, no cloud, no tracking." }
+ "extDesc": { "message": "Personal bookmark dashboard with boards, widgets, and 11 themes. Local-only, no cloud, no tracking." },
+ "cmdQuickSave": { "message": "Save current tab to Inbox" },
+ "quickSaveBadge": { "message": "OK" },
+ "quickSaveSaved": { "message": "Saved" },
+ "quickSaveNoTab": { "message": "No tab" }
}
diff --git a/manifest.firefox.json b/manifest.firefox.json
index 7bff759..fab6932 100644
--- a/manifest.firefox.json
+++ b/manifest.firefox.json
@@ -2,7 +2,7 @@
"manifest_version": 3,
"name": "__MSG_extName__",
"default_locale": "en",
- "version": "2.2.0",
+ "version": "2.3.0",
"description": "__MSG_extDesc__",
"author": "Hellion Online Media - Florian Wathling",
"homepage_url": "https://hellion-media.de",
@@ -11,9 +11,28 @@
"newtab": "newtab.html"
},
+ "background": {
+ "scripts": ["src/js/quicksave-core.js", "src/js/background.js"]
+ },
+
+ "action": {
+ "default_title": "Hellion Dashboard"
+ },
+
+ "commands": {
+ "quick-save": {
+ "suggested_key": {
+ "default": "Alt+Shift+S",
+ "mac": "Alt+Shift+S"
+ },
+ "description": "__MSG_cmdQuickSave__"
+ }
+ },
+
"permissions": [
"storage",
- "bookmarks"
+ "bookmarks",
+ "activeTab"
],
"browser_specific_settings": {
diff --git a/manifest.json b/manifest.json
index 94a4d25..cc5ed6f 100644
--- a/manifest.json
+++ b/manifest.json
@@ -2,16 +2,32 @@
"manifest_version": 3,
"name": "__MSG_extName__",
"default_locale": "en",
- "version": "2.2.0",
+ "version": "2.3.0",
"description": "__MSG_extDesc__",
"author": "Hellion Online Media - Florian Wathling",
"homepage_url": "https://hellion-media.de",
"chrome_url_overrides": {
"newtab": "newtab.html"
},
+ "background": {
+ "service_worker": "src/js/background.js"
+ },
+ "action": {
+ "default_title": "Hellion Dashboard"
+ },
+ "commands": {
+ "quick-save": {
+ "suggested_key": {
+ "default": "Alt+Shift+S",
+ "mac": "Alt+Shift+S"
+ },
+ "description": "__MSG_cmdQuickSave__"
+ }
+ },
"permissions": [
"storage",
- "bookmarks"
+ "bookmarks",
+ "activeTab"
],
"web_accessible_resources": [
{
diff --git a/manifest.opera.json b/manifest.opera.json
index 1c22625..942930d 100644
--- a/manifest.opera.json
+++ b/manifest.opera.json
@@ -2,7 +2,7 @@
"manifest_version": 3,
"name": "__MSG_extName__",
"default_locale": "en",
- "version": "2.2.0",
+ "version": "2.3.0",
"description": "__MSG_extDesc__",
"author": "Hellion Online Media - Florian Wathling",
"homepage_url": "https://hellion-media.de",
@@ -40,6 +40,16 @@
"default_title": "Hellion Dashboard"
},
+ "commands": {
+ "quick-save": {
+ "suggested_key": {
+ "default": "Alt+Shift+S",
+ "mac": "Alt+Shift+S"
+ },
+ "description": "__MSG_cmdQuickSave__"
+ }
+ },
+
"content_security_policy": {
"extension_pages": "script-src 'self'; object-src 'self'"
},
diff --git a/newtab.html b/newtab.html
index 781ee9c..0826aab 100644
--- a/newtab.html
+++ b/newtab.html
@@ -39,6 +39,10 @@
Darstellung
+