mirror of
https://github.com/hoornet/vega.git
synced 2026-04-24 06:40:01 -07:00
Bump to v0.2.1 — Batch 3 playtest fixes + auto-updater fix
- Fix: repost + quote buttons added to RootNote in ThreadView (Issue A) - Fix: switchAccount no longer silently goes read-only when nsec keychain entry is missing — nsec accounts stay logged out so the login button handles recovery; loginType field added to SavedAccount (Issue B) - Fix: macos-12 runner replaced with macos-13 in release.yml — macos-12 was deprecated by GitHub, causing macOS jobs to never run, which prevented latest.json from being assembled and broke the auto-updater for every user since v0.1.5 - Bump Cargo.toml version (was stuck at 0.1.10) - Release notes updated with v0.2.1 + v0.2.0 Phase 2 changelog - README: Windows unsigned installer note added - ROADMAP: NIP-05 monetization added to brainstorm backlog Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
15
.github/workflows/release.yml
vendored
15
.github/workflows/release.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
args: ''
|
||||
- platform: macos-latest
|
||||
args: '--target aarch64-apple-darwin'
|
||||
- platform: macos-12
|
||||
- platform: macos-13
|
||||
args: '--target x86_64-apple-darwin'
|
||||
|
||||
runs-on: ${{ matrix.platform }}
|
||||
@@ -66,6 +66,19 @@ jobs:
|
||||
|
||||
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.
|
||||
|
||||
### New in v0.2.1
|
||||
- **Fix: repost + quote in thread view** — thread view now shows repost and quote buttons on the root note (they were already on feed notes but were missing in threads)
|
||||
- **Fix: login persistence after Windows update** — nsec accounts whose keychain entry was lost after an OS update now stay logged out (login button visible) instead of silently becoming read-only
|
||||
|
||||
### New in v0.2.0 — Phase 2: Engagement & Reach
|
||||
- **Feed reply context** — replies show "↩ replying to @name" above the note; click to open the parent thread
|
||||
- **NIP-65 outbox model** — reads kind 10002 relay lists so you see notes from people who publish to their own relays; "Publish relay list to Nostr" button in Settings
|
||||
- **Notifications view** — 🔔 sidebar nav item; lists recent mentions with unread badge; badge clears on open
|
||||
- **DM unread badge** — messages nav item shows count of conversations with new messages; clears when conversation is opened
|
||||
- **Keyboard shortcuts** — `n` focus compose, `/` focus search, `j`/`k` navigate feed with highlight, `Esc` go back, `?` help overlay
|
||||
|
||||
### New in 0.1.7
|
||||
- **Per-account Lightning wallet** — NWC connection is now stored per account; switching accounts loads the correct wallet automatically
|
||||
- **New account creation in-app** — "Add account" now has a "New account" tab that generates a fresh keypair (no need to go through onboarding again)
|
||||
|
||||
@@ -18,6 +18,8 @@ Grab the latest release from the [Releases page](https://github.com/hoornet/wrys
|
||||
| macOS (Apple Silicon) | `aarch64.dmg` | open and drag to Applications |
|
||||
| macOS (Intel) | `x86_64.dmg` | open and drag to Applications |
|
||||
|
||||
**Windows note:** The installer is not yet code-signed. Windows SmartScreen will show an "Unknown publisher" warning — click "More info → Run anyway" to install.
|
||||
|
||||
## Features
|
||||
|
||||
**Identity & accounts**
|
||||
|
||||
@@ -96,10 +96,19 @@ Bugs found during testing are fixed before Phase N+1 starts. A release is cut be
|
||||
- Sign events via a remote signer (Nsecbunker, Amber, etc.)
|
||||
- Would complete the multi-account story for users who don't want nsec in keychain
|
||||
|
||||
### NIP-05 monetization (Phase 4 idea)
|
||||
- Offer a paid "Verified NIP-05 name" service (e.g. name@wrystr.app)
|
||||
- Would need a backend + domain; Wrystr talks to it; users pay sats via Lightning
|
||||
- Free tier: self-hosted as today; paid tier: managed registration
|
||||
|
||||
---
|
||||
|
||||
## What's already shipped
|
||||
|
||||
### v0.2.1 — Batch 3 playtest fixes
|
||||
- **Fix: repost + quote in thread view** — root note in thread view now shows repost and quote buttons (parity with feed cards)
|
||||
- **Fix: login persistence after Windows update** — nsec accounts with a lost keychain entry now stay logged out (login button visible) instead of silently going read-only
|
||||
|
||||
### v0.2.0 — Phase 2: Engagement & Reach
|
||||
- **Feed reply context** — replies show "↩ replying to @name" above the note; click to open the parent thread
|
||||
- **NIP-65 outbox model** — reads kind 10002 relay lists so you see notes from people who publish to their own relays; profile notes fetched via their write relays; "Publish relay list to Nostr" button in Settings
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "wrystr",
|
||||
"private": true,
|
||||
"version": "0.2.0",
|
||||
"version": "0.2.1",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wrystr"
|
||||
version = "0.1.10"
|
||||
version = "0.2.1"
|
||||
description = "Cross-platform Nostr desktop client with Lightning integration"
|
||||
authors = ["hoornet"]
|
||||
edition = "2021"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "Wrystr",
|
||||
"version": "0.2.0",
|
||||
"version": "0.2.1",
|
||||
"identifier": "com.hoornet.wrystr",
|
||||
"build": {
|
||||
"beforeDevCommand": "npm run dev",
|
||||
|
||||
@@ -5,7 +5,8 @@ import { useUserStore } from "../../stores/user";
|
||||
import { useProfile } from "../../hooks/useProfile";
|
||||
import { useReactionCount } from "../../hooks/useReactionCount";
|
||||
import { useZapCount } from "../../hooks/useZapCount";
|
||||
import { fetchReplies, publishReaction, publishReply, getNDK } from "../../lib/nostr";
|
||||
import { fetchReplies, publishReaction, publishReply, publishRepost, getNDK } from "../../lib/nostr";
|
||||
import { QuoteModal } from "../feed/QuoteModal";
|
||||
import { shortenPubkey, timeAgo } from "../../lib/utils";
|
||||
import { NoteContent } from "../feed/NoteContent";
|
||||
import { NoteCard } from "../feed/NoteCard";
|
||||
@@ -27,6 +28,9 @@ function RootNote({ event }: { event: NDKEvent }) {
|
||||
});
|
||||
const [liking, setLiking] = useState(false);
|
||||
const [showZap, setShowZap] = useState(false);
|
||||
const [reposting, setReposting] = useState(false);
|
||||
const [reposted, setReposted] = useState(false);
|
||||
const [showQuote, setShowQuote] = useState(false);
|
||||
const hasLightning = !!(profile?.lud16 || profile?.lud06);
|
||||
|
||||
const handleLike = async () => {
|
||||
@@ -44,6 +48,17 @@ function RootNote({ event }: { event: NDKEvent }) {
|
||||
}
|
||||
};
|
||||
|
||||
const handleRepost = async () => {
|
||||
if (reposting || reposted) return;
|
||||
setReposting(true);
|
||||
try {
|
||||
await publishRepost(event);
|
||||
setReposted(true);
|
||||
} finally {
|
||||
setReposting(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="px-4 py-4 border-b border-border">
|
||||
<div className="flex gap-3 mb-3">
|
||||
@@ -79,6 +94,21 @@ function RootNote({ event }: { event: NDKEvent }) {
|
||||
>
|
||||
{liked ? "♥" : "♡"}{reactionCount !== null && reactionCount > 0 ? ` ${reactionCount}` : liked ? " liked" : " like"}
|
||||
</button>
|
||||
<button
|
||||
onClick={handleRepost}
|
||||
disabled={reposting || reposted}
|
||||
className={`text-[11px] transition-colors disabled:cursor-default ${
|
||||
reposted ? "text-accent" : "text-text-dim hover:text-accent"
|
||||
}`}
|
||||
>
|
||||
{reposted ? "reposted ✓" : reposting ? "…" : "repost"}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setShowQuote(true)}
|
||||
className="text-[11px] text-text-dim hover:text-text transition-colors"
|
||||
>
|
||||
quote
|
||||
</button>
|
||||
{hasLightning && (
|
||||
<button
|
||||
onClick={() => setShowZap(true)}
|
||||
@@ -99,6 +129,15 @@ function RootNote({ event }: { event: NDKEvent }) {
|
||||
onClose={() => setShowZap(false)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{showQuote && (
|
||||
<QuoteModal
|
||||
event={event}
|
||||
authorName={name}
|
||||
authorAvatar={avatar}
|
||||
onClose={() => setShowQuote(false)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ export interface SavedAccount {
|
||||
npub: string;
|
||||
name?: string;
|
||||
picture?: string;
|
||||
loginType?: "nsec" | "pubkey";
|
||||
}
|
||||
|
||||
// In-memory signer cache — survives account switches within a session.
|
||||
@@ -98,7 +99,7 @@ export const useUserStore = create<UserState>((set, get) => ({
|
||||
_signerCache.set(pubkey, signer);
|
||||
|
||||
// Update accounts list
|
||||
const accounts = upsertAccount(get().accounts, { pubkey, npub });
|
||||
const accounts = upsertAccount(get().accounts, { pubkey, npub, loginType: "nsec" });
|
||||
persistAccounts(accounts);
|
||||
|
||||
set({ pubkey, npub, loggedIn: true, loginError: null, accounts });
|
||||
@@ -142,7 +143,7 @@ export const useUserStore = create<UserState>((set, get) => ({
|
||||
const npub = nip19.npubEncode(pubkey);
|
||||
|
||||
// Update accounts list
|
||||
const accounts = upsertAccount(get().accounts, { pubkey, npub });
|
||||
const accounts = upsertAccount(get().accounts, { pubkey, npub, loginType: "pubkey" });
|
||||
persistAccounts(accounts);
|
||||
|
||||
set({ pubkey, npub, loggedIn: true, loginError: null, accounts });
|
||||
@@ -229,7 +230,13 @@ export const useUserStore = create<UserState>((set, get) => ({
|
||||
// Keychain unavailable
|
||||
}
|
||||
if (!succeeded) {
|
||||
await get().loginWithPubkey(pubkey);
|
||||
const account = get().accounts.find((a) => a.pubkey === pubkey);
|
||||
if (account?.loginType === "pubkey") {
|
||||
// Deliberately read-only (npub) account — correct behavior
|
||||
await get().loginWithPubkey(pubkey);
|
||||
}
|
||||
// else: nsec account whose keychain entry was lost.
|
||||
// Stay logged out; user sees AccountSwitcher "login" button to re-enter nsec.
|
||||
}
|
||||
// Always land on feed to avoid stale UI from previous account's view
|
||||
useUIStore.getState().setView("feed");
|
||||
|
||||
Reference in New Issue
Block a user