diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index dbd6576..54454f9 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -77,28 +77,47 @@ jobs: sha256sum *.zip > checksums-sha256.txt cat checksums-sha256.txt - # Gitea-native Release-Action. Legt das Release an, falls der Tag noch - # keins hat, oder aktualisiert das bestehende und haengt die Assets an. - # Der auto-injizierte GITHUB_TOKEN auf Gitea Actions hat Gitea-API-Scope - # und reicht fuer Release-Write. - - name: Attach to Gitea release - uses: https://gitea.com/actions/release-action@main - with: - files: |- - dist/hellion-newtab-${{ steps.version.outputs.tag }}-chrome.zip - dist/hellion-newtab-${{ steps.version.outputs.tag }}-firefox.zip - dist/hellion-newtab-${{ steps.version.outputs.tag }}-opera.zip - dist/checksums-sha256.txt - api_key: ${{ secrets.GITHUB_TOKEN }} - body: | - ## Hellion NewTab ${{ steps.version.outputs.tag }} + # Release per Gitea-API (curl), NICHT via gitea.com/actions/release-action: die ist `using: go` + # und stirbt auf diesem Runner mit exit 127 ("go not found"), weil act_runner v0.6.1 die go-Action + # weder im Job-Image noch im Runner kompiliert bekommt. curl + python3 sind im Job-Image vorhanden + # und laufen als normaler Step -> unabhaengig von go-Toolchain, Action-Cache und @main-Drift. + # GITHUB_API_URL/GITHUB_REPOSITORY/GITHUB_TOKEN injiziert Gitea Actions automatisch. + - name: Create release & upload assets (Gitea API) + env: + GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAG: ${{ steps.version.outputs.tag }} + run: | + set -euo pipefail + API="${GITHUB_API_URL:-https://gitea.hellion-forge.cloud/api/v1}" + REPO="${GITHUB_REPOSITORY}" + AUTH="Authorization: token ${GITEA_TOKEN}" - ### Installation - - **Chrome / Edge / Brave / Vivaldi:** `hellion-newtab-${{ steps.version.outputs.tag }}-chrome.zip` - - **Firefox:** `hellion-newtab-${{ steps.version.outputs.tag }}-firefox.zip` - - **Opera / Opera GX:** `hellion-newtab-${{ steps.version.outputs.tag }}-opera.zip` + # Release-Request-JSON (Body inkl. Installationshinweise) als python-Einzeiler bauen + # (mehrzeilig wuerde den YAML-run-Block brechen: Zeilen auf Spalte 0). + REQ=$(python3 -c 'import json,os; t=os.environ["TAG"]; body="## Hellion NewTab "+t+"\n\n### Installation\n- **Chrome / Edge / Brave / Vivaldi:** `hellion-newtab-"+t+"-chrome.zip`\n- **Firefox:** `hellion-newtab-"+t+"-firefox.zip`\n- **Opera / Opera GX:** `hellion-newtab-"+t+"-opera.zip`\n\nVollstaendige Installationsanleitung siehe README.\n\n### Checksums\n`checksums-sha256.txt` zum Verifizieren der Dateiintegritaet."; print(json.dumps({"tag_name": t, "name": "Hellion NewTab "+t, "body": body}))') - Vollstaendige Installationsanleitung siehe README. + # Idempotent: existierendes Release zum Tag wiederverwenden, sonst anlegen. + REL_ID=$(curl -sf -H "$AUTH" "$API/repos/$REPO/releases/tags/$TAG" \ + | python3 -c 'import sys,json;print(json.load(sys.stdin).get("id",""))' 2>/dev/null || true) + if [ -z "$REL_ID" ]; then + REL_ID=$(printf '%s' "$REQ" \ + | curl -sf -X POST -H "$AUTH" -H "Content-Type: application/json" -d @- "$API/repos/$REPO/releases" \ + | python3 -c 'import sys,json;print(json.load(sys.stdin)["id"])') + echo "Release angelegt: $REL_ID" + else + echo "Release existiert bereits, wiederverwenden: $REL_ID" + fi - ### Checksums - `checksums-sha256.txt` zum Verifizieren der Dateiintegritaet. + # Vorhandene gleichnamige Assets entfernen (idempotent bei Re-Runs), dann hochladen. + EXIST=$(curl -sf -H "$AUTH" "$API/repos/$REPO/releases/$REL_ID/assets" 2>/dev/null || echo '[]') + for f in dist/hellion-newtab-$TAG-chrome.zip dist/hellion-newtab-$TAG-firefox.zip dist/hellion-newtab-$TAG-opera.zip dist/checksums-sha256.txt; do + name=$(basename "$f") + aid=$(printf '%s' "$EXIST" | NAME="$name" python3 -c 'import sys,json,os;n=os.environ["NAME"];print(next((a["id"] for a in json.load(sys.stdin) if a.get("name")==n), ""))' 2>/dev/null || true) + if [ -n "$aid" ]; then + echo "ersetze vorhandenes Asset $name (id $aid)" + curl -sf -X DELETE -H "$AUTH" "$API/repos/$REPO/releases/$REL_ID/assets/$aid" >/dev/null || true + fi + echo "Upload $name ..." + curl -sf -X POST -H "$AUTH" -F "attachment=@$f" "$API/repos/$REPO/releases/$REL_ID/assets?name=$name" >/dev/null + done + echo "Release $TAG fertig: alle Assets hochgeladen." diff --git a/CHANGELOG.md b/CHANGELOG.md index c21355d..31214b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,19 @@ All notable changes per version. Format based on [Keep a Changelog](https://keep --- +## [2.4.0] — 2026-06-15 + +### Added +- **Custom theme builder** — A new "Custom" tile in the theme picker opens an inline panel with six colour pickers (accent, background, board surface, and three text levels). Colours apply live to the dashboard; the accent drives the derived glow, border and toggle tints via `color-mix`. A non-blocking WCAG contrast indicator flags hard-to-read text/background combinations without preventing the choice. The custom theme persists across reloads and can be combined with a custom background image. A reset button returns the pickers to neutral defaults. New DE/EN i18n strings; the `` pickers are labelled for accessibility. +- **Custom background via https URL** — The background URL field now accepts `https://` images in addition to local uploads (http stays out to avoid mixed content). A privacy note explains that a URL-loaded image is fetched from the remote server on every new tab. + +### Changed +- Uploaded background images are downscaled (to the longest screen edge, capped at 2560px) and re-encoded as WebP before storage, to protect the `chrome.storage.local` quota. +- The extension-page CSP gains `img-src 'self' https: data: blob:` so https and data-URL backgrounds load deterministically instead of relying on the browser default. +- Onboarding slide 3 wording no longer hard-codes a fixed theme count. + +--- + ## [2.3.0] — 2026-06-14 ### Added diff --git a/manifest.firefox.json b/manifest.firefox.json index fab6932..c3665c7 100644 --- a/manifest.firefox.json +++ b/manifest.firefox.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "__MSG_extName__", "default_locale": "en", - "version": "2.3.0", + "version": "2.4.0", "description": "__MSG_extDesc__", "author": "Hellion Online Media - Florian Wathling", "homepage_url": "https://hellion-media.de", @@ -54,7 +54,7 @@ } ], "content_security_policy": { - "extension_pages": "script-src 'self'; object-src 'self'" + "extension_pages": "script-src 'self'; object-src 'self'; img-src 'self' https: data: blob:" }, "icons": { "16": "assets/icons/icon16.png", diff --git a/manifest.json b/manifest.json index cc5ed6f..a24275d 100644 --- a/manifest.json +++ b/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "__MSG_extName__", "default_locale": "en", - "version": "2.3.0", + "version": "2.4.0", "description": "__MSG_extDesc__", "author": "Hellion Online Media - Florian Wathling", "homepage_url": "https://hellion-media.de", @@ -36,7 +36,7 @@ } ], "content_security_policy": { - "extension_pages": "script-src 'self'; object-src 'self'" + "extension_pages": "script-src 'self'; object-src 'self'; img-src 'self' https: data: blob:" }, "icons": { "16": "assets/icons/icon16.png", diff --git a/manifest.opera.json b/manifest.opera.json index 942930d..aea38e1 100644 --- a/manifest.opera.json +++ b/manifest.opera.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "__MSG_extName__", "default_locale": "en", - "version": "2.3.0", + "version": "2.4.0", "description": "__MSG_extDesc__", "author": "Hellion Online Media - Florian Wathling", "homepage_url": "https://hellion-media.de", @@ -51,7 +51,7 @@ }, "content_security_policy": { - "extension_pages": "script-src 'self'; object-src 'self'" + "extension_pages": "script-src 'self'; object-src 'self'; img-src 'self' https: data: blob:" }, "icons": { "16": "assets/icons/icon16.png", diff --git a/newtab.html b/newtab.html index 0826aab..f471ce0 100644 --- a/newtab.html +++ b/newtab.html @@ -241,7 +241,7 @@