name: Release

on:
  push:
    tags:
      - 'v*'

permissions:
  contents: write

jobs:
  release:
    permissions:
      contents: write
    strategy:
      fail-fast: false
      matrix:
        include:
          - platform: ubuntu-22.04
            args: ''
          - platform: windows-latest
            args: ''
          - platform: macos-latest
            args: '--target aarch64-apple-darwin'

    runs-on: ${{ matrix.platform }}

    steps:
      - uses: actions/checkout@v6

      - name: Setup Node.js
        uses: actions/setup-node@v5
        with:
          node-version: 'lts/*'

      - name: Install Rust stable
        uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin' || matrix.platform == 'macos-12' && 'x86_64-apple-darwin' || '' }}

      - name: Install Linux dependencies
        if: matrix.platform == 'ubuntu-22.04'
        run: |
          sudo apt-get update
          sudo apt-get install -y \
            libwebkit2gtk-4.1-dev \
            build-essential \
            libssl-dev \
            libayatana-appindicator3-dev \
            librsvg2-dev \
            patchelf

      - name: Install frontend dependencies
        run: npm install

      - name: Build and release
        uses: tauri-apps/tauri-action@v0
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
          TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
        with:
          tagName: ${{ github.ref_name }}
          releaseName: Vega ${{ github.ref_name }}
          releaseBody: |
            ## Vega ${{ github.ref_name }}

            Cross-platform Nostr desktop client — polished UI, deep Lightning integration, first-class long-form writing.

            > **Windows note:** The installer is not yet code-signed. Windows SmartScreen will show an "Unknown publisher" warning — click "More info → Run anyway" to install.

            ### v0.14.0 — Vega moves to its own app identifier

            Vega's internal app identifier changes from `com.hoornet.vega` to `com.veganostr.Vega`, so it is anchored to a domain the project controls. This is a prerequisite for publishing Vega on Flathub and winget, and it makes the app's identity consistent across every platform.

            **Your data comes with you.** On first launch, v0.14.0 moves your existing data directory across automatically — cached notes and profiles, the embedded relay's database, your themes, drafts, podcast subscriptions and article read-state. Your keys are stored in the OS keychain and are not affected at all, so you stay logged in.

            > **Upgrading on Windows:** because the identifier changed, Windows treats this as a new application, so v0.14.0 installs alongside v0.13.2 instead of replacing it. Your data is carried over — you can uninstall the old "Vega" entry from Add/Remove Programs afterwards. This is a one-time step; future updates will upgrade in place as normal.

            ### v0.13.2 — Mute-aware search, a tidier compose box & a resizable sidebar

            Three community-requested improvements plus a couple of nice touches.

            - **Search now respects your mute list.** Notes, articles, and people from muted accounts — and posts matching your muted keywords — no longer show up in search results, just like in the feed. (#7)
            - **The compose box collapses when idle.** "What's on your mind?" now sits as a single line until you click it, then expands to full height with the toolbar — reclaiming space at the top of the feed. (#6)
            - **The left sidebar is resizable.** Drag its right edge to set the width; double-click to reset. Your choice is remembered between sessions. (#6)
            - **The update banner shows what's new.** When an update is available, click "What's new" to read that version's changes inline, with a link to the full changelog on GitHub.
            - **Under the hood:** migrated the build to Vite 8 and dropped a vulnerable `esbuild` dev-server dependency.

            ### v0.13.1 — Article reader: scroll lock fix + click-to-zoom

            A targeted fix for a long-standing article-reader bug on Linux.

            - **Scroll lock fixed.** Articles with body images would refuse to scroll past a certain point on Linux (WebKitGTK). Body images now sit in a reserved layout box that survives WebKit's image re-decode loop, so the article scrolls all the way through.
            - **Click any body image to open it full-size.** The existing image lightbox is now wired up to article body images — click to enlarge, click again (or press Escape, or hit the ✕) to close. Arrow keys navigate between images in the article.

            ### v0.13.0 — Visual overhaul: themes, readability & accessibility

            A broad visual pass — typography, colour, and icons reworked across the app — plus two new accessibility features and a round of feed fixes.

            **Themes**

            - All four home-grown themes — **Midnight, Light, Sepia, Hackerman** — were redesigned as proper palettes: even background-elevation steps, a real three-tier text hierarchy with verified contrast, and considered accents. The community palettes (Catppuccin, Nord, Gruvbox) are unchanged.
            - **New "Reader" theme** — a warm, low-glare cream palette for comfortable long reading. Pairs naturally with the long-form article view.

            **Accessibility**

            - **Easy-Read Font** (Settings → Appearance) — switches the interface to Atkinson Hyperlegible, a typeface designed by the Braille Institute for legibility, with slightly wider letter-spacing and line-height. Helps dyslexic readers and anyone in a long reading session.
            - **Your secret key is now viewable** in Settings → Identity — reveal, hide, copy. Previously the `nsec` was unreachable after onboarding; you can now back it up or move to another client at any time.

            **Interface**

            - The UI font is now a system sans-serif rather than monospace; base text is a little larger with more line-height. Sidebar labels are Title Case.
            - **Lucide icon set** — the sidebar's Unicode glyphs are replaced with crisp SVG icons that render consistently at any size and zoom.
            - Redrawn default (Midnight) theme with deeper, calmer contrast; rounded avatars; stronger article-card titles.

            **Feed fixes**

            - Fixed cards overlapping or leaving gaps while scrolling, and an upward-scroll flicker — three separate row-measurement bugs in the v0.12.17 virtualized feed.

            **Onboarding**

            - A step-progress indicator across the create-key flow, and an "I'll back up my key later" option for people who want to explore the app first (the key stays retrievable in Settings → Identity).

            ### v0.12.17 — Infinite scroll & a virtualized feed

            The feed no longer stops at a fixed number of notes. Scroll to the bottom and older notes load automatically — no manual Refresh.

            - **Infinite scroll on the Global feed.** Reaching the bottom auto-loads the next page of older notes (up to 1,000), with a brief "Loading older notes…" indicator during each fetch.
            - **Virtualized feed list.** Only the notes actually on screen (~25–35 cards) are kept in the page at any time, regardless of how far you scroll. This structurally bounds memory — the WebKitGTK image-memory growth behind past Linux crashes can't accumulate, because off-screen note images are released as you scroll past them.
            - Verified on Linux: ~1,000 notes scrolled, memory oscillated and settled around 1.15 GB — bounded regardless of scroll depth.

            ### v0.12.16 — Security hardening

            A defense-in-depth pass on link and text rendering, prompted by a CodeQL code-scanning review. No user-facing changes, and no exploitable vulnerability was found — note URLs were already scheme-constrained upstream — but the rendering sinks are now hardened directly.

            - **External links** now route every `href` through a scheme guard that permits only `http(s)://`. A `javascript:` or `data:` URI in note content can never reach a clickable link, even if the content parser changes in future.
            - **Podcast description text** is now stripped of HTML tags with a loop-until-stable pass, so split or nested tags can't survive sanitization.

            ### v0.12.15 — Honest update banner on Linux

            The "Update & restart" banner now adapts to how Vega was installed. On a package-manager install — the AUR `vega-nostr-git` package, or a `.deb`/`.rpm` — the in-app updater can't replace a root-owned binary under `/usr`, so the button did nothing. The banner now detects the install kind and shows the right path:

            - **Arch (AUR install):** shows the update command inline with a "Copy command" button — `yay -S vega-nostr-git`.
            - **Debian / Fedora (.deb / .rpm):** a "View release" button opens the GitHub release page for a manual download.
            - **Windows, macOS, AppImage, portable builds:** unchanged — one-click "Update & restart" still works.

            The new-version notification itself always worked everywhere; only the install action needed to become install-method-aware.

            ### v0.12.14 — Fix macOS auto-updater

            macOS users on Apple Silicon now get in-app update notifications. Since before v0.12.9, the macOS build shipped a `.dmg` for manual download but never produced the `.app.tar.gz` updater artifact — so `latest.json` carried no macOS entry and the in-app updater stayed silent on Macs. The `app` bundle target was missing from the build config; that's the target that generates the updater archive and its signature. Linux and Windows auto-update were unaffected throughout.

            **One-time manual step for Mac users:** if you're on v0.12.13 or earlier, download v0.12.14 manually from this page once. Auto-updates work from v0.12.14 onward.

            ### v0.12.13 — Podcast subscription merge on first upgrade

            Fixes a data-loss edge case introduced by v0.12.12. If you'd been using Vega on **multiple machines before v0.12.12**, the first machine to upgrade would publish its list to the relay; the second machine to upgrade would then silently overwrite its own local-only additions with the cloud list. The first-time hydrate now **unions** the pre-upgrade local list with the cloud list and re-publishes the merger, so subscriptions you'd added on any pre-upgrade machine all survive. Subsequent hydrates keep the cloud-wins behavior — removals on one machine still propagate everywhere as expected.

            This only matters for the upgrade window. Once your subscription list has fully synced across all your devices, behavior is identical to v0.12.12.

            ### v0.12.12 — Podcasts that follow your account

            Your "My Podcasts" list now lives on Nostr, keyed to your pubkey. Reinstall the app on a new machine, switch devices, wipe local storage — your subscriptions come back automatically as long as you sign in with the same key.

            - **Published as a NIP-51 kind 30003 bookmark set** with `d="podcasts"`. Feed URLs are standard `r` tags; rich metadata (title, artwork, author, description, Podcast Index ID) rides along in the event content so the list renders offline on first paint.
            - **Per-account isolation** — each pubkey has its own list. Switching accounts swaps the subscriptions immediately; a previous account's list never leaks under the new signer.
            - **Cloud-wins hydration** on login. If the relay has a newer list, it replaces local. If the cloud is empty but you have local subscriptions, your list is published as the initial seed.
            - **Existing users:** your current subscription list is automatically adopted into your active account on first launch.
            - **Read-only accounts (`npub` login):** you can still see your list, but changes don't publish (no signer).

            ### v0.12.11 — Read-only mode polish

            If you haven't created a key yet, or you're signed in with just an `npub` (view-only), the app now behaves correctly throughout: no broken Publish buttons, no dead-end "Not logged in" errors.

            - **Sidebar shows only the views that work without a signer** — Feed, Articles, Media, Podcasts, Search, Follows, Relays, Settings, Support. Account-bound entries (Bookmarks, Messages, Notifications, Zaps, V4V) are hidden until you sign in.
            - **Write surfaces are guarded everywhere.** Compose box, reply box, reactions, repost, quote, zap, bookmark, follow/unfollow, mute, profile edit, article publish, poll vote, relay-list publish — all properly hidden or replaced with a "Sign in" CTA that opens the login dialog.
            - **Read-only banner now fires for npub-only logins too**, not just fully logged-out state.
            - **The original bug:** in v0.12.10 and earlier, opening the article editor without a signer and clicking Publish raised `Failed to publish: Error: Not logged in`. That path no longer exists.

            ### v0.12.10 — Security update

            Dependency security bumps only. No functional changes.

            - **Tauri 2.10.3 → 2.11.1** — fixes an Origin Confusion issue where remote pages could invoke local-only IPC commands. Brings updated webview (wry 0.54 → 0.55), windowing (tao 0.34 → 0.35), and system tray (tray-icon 0.21 → 0.23) layers.
            - **rustls-webpki 0.103.10 → 0.103.13** — fixes a high-severity denial-of-service panic on malformed CRL BIT STRING, plus two name-constraint validation issues.
            - **rand 0.8.5 → 0.8.6** and **rand 0.9.2 → 0.9.4** — fix soundness with custom loggers using `rand::rng()`.
            - **dompurify 3.3.2 → 3.4.2** — fixes four sanitization bypass issues affecting `FORBID_TAGS`, `SAFE_FOR_TEMPLATES`, and `CUSTOM_ELEMENT_HANDLING`.
            - **postcss 8.5.8 → 8.5.14** — fixes XSS via unescaped `</style>` in CSS stringify output.

            `glib` stays at 0.18.5 because the gtk-rs / webkit2gtk stack is pinned there upstream by Tauri's wry crate; that one waits for upstream.

            ### v0.12.9 — Web of Trust everywhere

            - **Web of Trust filter now applies everywhere.** Previously it only hid notes from outside your social graph on the global feed. It now also filters all feed tabs (global, following, trending), reaction pills, and zap totals. Zaps are filtered by the actual zapper's pubkey (from the inner zap request), not the outer LNURL service pubkey.
            - **Removed the "new account" badge** on notes. The proxy was unreliable — kind-0 `created_at` is "profile last updated," not "account created," so it flagged anyone who tweaked their bio recently. Dropped until there's a real signal to use.

            ### v0.12.8 — Fix Linux OOM crash

            - **Fix Linux memory crash** — Vega no longer crashes on Linux. Memory now oscillates at ~1.1–1.6 GB during heavy use instead of climbing to 8–12 GB. Root cause traced to v0.12.6: the Blossom SHA-256 URL auto-detection regex caused 3–5× more `<img>` elements per feed page, which combined with WebKitGTK's weak bitmap eviction pushed the WebKit process past its 8 GB self-kill threshold. Blossom auto-detection is temporarily disabled pending proper validation in a future release.
            - **Feed depths restored** — the v0.12.7 OOM firefighting that slashed follow/global feed limits to 30 is reverted; follow feed now fetches 100 and global caches up to 200, matching pre-crisis v0.12.6 behavior.
            - **WebKit rendering fix** — `WEBKIT_FORCE_SOFTWARE_RENDERING=1` keeps the Wayland compositor path intact on Hyprland.
            - **Notification fetch dedup** — `fetchNotifications` was firing 3× in the first 8 seconds of login; now fires once and the first background poll is delayed to 90s.

            ### v0.12.7 — Upload Fixes

            - **Image uploads fixed** — updated to current NIP-96 endpoints for nostr.build and files.sovbit.host; removed dead services (void.cat, nostrcheck.me)
            - **SVG upload blocked** — SVG files are now rejected with a clear error message; they were silently uploading but rendering as broken images on all Nostr clients
            - **NIP-98 payload hash** — upload auth headers now include the required SHA-256 body hash for strict NIP-96 servers

            ### v0.12.5 — UI Polish & Consistency

            - **Comprehensive UI polish** — 14 rounds of systematic fixes across every view: sentence case on all button labels, Unicode ellipsis (…) and × throughout, consistent theme tokens replacing all hard-coded colors
            - **Fix V4V auto-streaming** — disabling streaming mid-episode now stays off; previously any play/pause/seek event would re-engage auto-streaming
            - **Production-silent logging** — all debug output now goes through `debug.ts` and is stripped in production builds; zero console leaks
            - **Accessibility** — hover title tooltips on all truncated text, focus rings on interactive elements, aria-labels on all icon-only buttons
            - **Theme consistency** — all amber/gray/white hard-coded colors replaced with theme tokens; correct across all 7 themes

            ### v0.12.4 — Polls, Custom Relay & UI Polish
            - **NIP-1068 Polls** — create polls from the compose box, vote on polls in the feed, animated result bars with vote counts and percentages, per-pubkey dedup, expiry support
            - **Custom Go relay** — switched default relay from strfry to Vega's own Go relay (`wss://relay2.veganostr.com`) with 19 NIPs including NIP-45 COUNT, NIP-50 Search, and NIP-77 Negentropy
            - **Note action icons** — replaced text labels (reply/repost/share/save) with icons, added tooltips on hover, dot separators for visual clarity
            - **Sidebar icons** — distinct icons for V4V (📡) vs Zaps (⚡), better icons for podcasts (🎙), follows (👥), bookmarks (★)
            - **Fix duplicate search results** — people search now deduplicates by pubkey across relays
            - **Fix thread indentation** — deep threads no longer overflow on narrow/half-screen windows; indent capped at depth 3 with relative spacing

            ### v0.12.3 — Fix Direct Messages
            - **Fix DMs not loading** — NIP-17 gift-wrapped messages were silently dropped by NDK's fetchEvents; switched to subscribe-based fetch that correctly receives kind 1059 events
            - **Repo cleanup** — hardened .gitignore, updated AGENTS.md and ROADMAP.md

            ### v0.12.2 — Vega Public Relay
            - **`wss://relay2.veganostr.com`** — Vega's custom Go relay, included by default for all users
            - Existing users get the relay auto-added on upgrade (one-time migration)

            ### v0.12.1 — Fixes
            - **Fix empty Media feed** — widened time window from 2h to 24h so media notes actually appear
            - **Fix empty Trending feed** — retry once after 3s when relays return nothing on startup
            - **Read-only mode banner** — persistent amber warning at top of app when not signed in
            - **Larger account badge** — avatar and name more prominent when logged in

            ### v0.12.0 — Podcasts & Value 4 Value
            - **Built-in podcast player** — search and play podcasts via Fountain.fm with Podcast Index enrichment
            - **V4V streaming** — stream sats per minute to podcast creators via Lightning (keysend + LNURL-pay)
            - **Auto-streaming** — enable once, V4V starts automatically on every supported episode at your chosen rate
            - **Per-episode caps & weekly budgets** — set spending limits; streaming stops automatically when caps are reached
            - **V4V sidebar section** — dedicated dashboard with live status, budget bars, stats, settings, and full streaming history
            - **Recipient breakdown** — see exactly who gets paid and their split percentages
            - **Accessibility** — WCAG AA contrast compliance, ARIA labels, reduced motion support
            - **Media pause on navigation** — video/audio automatically pauses when navigating between views
            - **Performance** — React.memo, granular Zustand selectors, code splitting for faster renders
            - **Podcast player stability** — 15s loading timeout, auto-stop V4V on audio failure

            ### v0.11.0 — Embedded Relay & Polish
            - Embedded Nostr relay, naddr links, new themes, follower badges, bookmark + relay pool fixes

            ### v0.10.1 — Search Reliability
            - Search resilience, nostr: URI prefix support in search

            ### v0.10.0 — Renamed to Vega + UX Improvements
            - **Renamed from Wrystr to Vega** — named after Jurij Vega (1754–1802), Slovenian mathematician and artillery officer. Fresh identity, same mission: a desktop Nostr client built for writers.
            - **Paste nevent/note1/naddr in search** — pasting a Nostr event link navigates directly to the note or article (GitHub #2)
            - **Copy npub from profiles** — click the pubkey on any profile to copy the full npub to clipboard (GitHub #2)
            - **Zap reliability fix** — custom outbox relays replace broken default (purplepag.es DNS failure), 45s timeout prevents indefinite hang
            - **Zap history note preview** — zap entries now show a preview of the zapped note with click-to-navigate
            - **Follower notification dedup** — fixed repeated OS notifications for the same follower (in-memory store now updated alongside DB)
            - **Data migration** — existing Wrystr users automatically migrate settings, database, and keychain on first launch

            ### Previous: v0.9.11 — Notifications & Bookmarks Polish
            - Follower notifications cleaned up, follower OS notification dedup, article bookmarks fixed

            ### Previous: v0.9.10 — Instant Everything
            - SQLite-backed followers, bookmarks, and articles cache; instant own-profile load

            ### Previous: v0.9.8–v0.9.9 — Web of Trust, Speed & Linux Fix
            - Web of Trust (Vertex DVM), SQLite-backed notifications, instant threads, Linux upload fix, trending reliability

            ### Previous: v0.9.0–v0.9.7 — Reactions, Search, Threads & Themes
            - Grouped emoji reactions, advanced search (NIP-50), follows view, nested thread trees, 7 color themes, font size presets, relay management, live feed, NIP-46 remote signer

            ### Previous highlights
            - v0.8.x: Trending feed, media feed, profile gallery, OS notifications, NIP-05 badges, hashtag pages, keyword muting, emoji picker, data export, relay health checker
            - v0.7.x: NIP-98 uploads, markdown toolbar, multi-draft management, advanced search with modifiers
            - v0.6.x: Article discovery feed, article cards, article search
            - v0.5.x and earlier: Note sharing, reply counts, image lightbox, bookmarks, DMs, multi-account, system tray, auto-updater

            ### Install

            **Linux (Ubuntu / Debian / Mint):** Download the `.deb` and run:
            ```
            sudo dpkg -i vega_*.deb
            ```
            **Linux (Fedora / openSUSE):** Download the `.rpm` and run:
            ```
            sudo rpm -i vega-*.rpm          # Fedora
            sudo zypper install vega-*.rpm  # openSUSE
            ```
            **Linux (Arch / Manjaro):** Install from the AUR:
            ```
            yay -S vega-nostr-git
            ```

            **Windows:** Download the `.exe` installer and run it.
            **macOS (Apple Silicon):** Download the `aarch64.dmg` and open it.

            ---
            ⚡ Find Vega useful? [Zap the developer](https://github.com/hoornet/vega#support) or star the repo.
          releaseDraft: false
          prerelease: false
          includeUpdaterJson: true
          args: ${{ matrix.args }}
