mirror of
https://github.com/hoornet/vega.git
synced 2026-05-10 22:29:11 -07:00
Bump version to 0.1.7 — Windows playtest fixes
Critical: - NWC wallet now stored per-account (wrystr_nwc_<pubkey>); switching accounts loads the correct wallet automatically - Clear NDK signer before account switch to prevent race where old account could sign outgoing events - LoginModal: add "New account" tab to create a fresh keypair inline (same flow as onboarding, with nsec copy + confirmation checkbox) - ThreadView: add like + zap action row to the root note (was missing) UX: - Zap button now conditional on lud16/lud06 (NoteCard, ProfileView, RootNote) — no zap button shown for profiles without Lightning - Remove "200 notes" counter from sidebar footer - AccountSwitcher: larger active account avatar (w-8), name more prominent; sign-out/remove moved into dropdown only Quick wins: - AboutView: add GitHub Sponsors link - ComposeBox: paste image from clipboard → uploads via nostr.build, inserts URL at cursor with "uploading image…" status Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
import { useState, useRef } from "react";
|
||||
import { publishNote } from "../../lib/nostr";
|
||||
import { uploadImage } from "../../lib/upload";
|
||||
import { useUserStore } from "../../stores/user";
|
||||
import { shortenPubkey } from "../../lib/utils";
|
||||
|
||||
export function ComposeBox({ onPublished }: { onPublished?: () => void }) {
|
||||
const [text, setText] = useState("");
|
||||
const [publishing, setPublishing] = useState(false);
|
||||
const [uploading, setUploading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
||||
|
||||
@@ -15,7 +17,35 @@ export function ComposeBox({ onPublished }: { onPublished?: () => void }) {
|
||||
|
||||
const charCount = text.length;
|
||||
const overLimit = charCount > 280;
|
||||
const canPost = text.trim().length > 0 && !overLimit && !publishing;
|
||||
const canPost = text.trim().length > 0 && !overLimit && !publishing && !uploading;
|
||||
|
||||
const handlePaste = async (e: React.ClipboardEvent<HTMLTextAreaElement>) => {
|
||||
const file = Array.from(e.clipboardData.files).find((f) => f.type.startsWith("image/"));
|
||||
if (!file) return;
|
||||
e.preventDefault();
|
||||
setUploading(true);
|
||||
setError(null);
|
||||
try {
|
||||
const url = await uploadImage(file);
|
||||
const ta = textareaRef.current;
|
||||
if (ta) {
|
||||
const start = ta.selectionStart ?? text.length;
|
||||
const end = ta.selectionEnd ?? text.length;
|
||||
const next = text.slice(0, start) + url + text.slice(end);
|
||||
setText(next);
|
||||
setTimeout(() => {
|
||||
ta.selectionStart = ta.selectionEnd = start + url.length;
|
||||
ta.focus();
|
||||
}, 0);
|
||||
} else {
|
||||
setText((t) => t + url);
|
||||
}
|
||||
} catch (err) {
|
||||
setError(`Image upload failed: ${err}`);
|
||||
} finally {
|
||||
setUploading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||||
if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
|
||||
@@ -66,6 +96,7 @@ export function ComposeBox({ onPublished }: { onPublished?: () => void }) {
|
||||
value={text}
|
||||
onChange={(e) => setText(e.target.value)}
|
||||
onKeyDown={handleKeyDown}
|
||||
onPaste={handlePaste}
|
||||
placeholder="What's on your mind?"
|
||||
rows={3}
|
||||
className="w-full bg-transparent text-text text-[13px] placeholder:text-text-dim resize-none focus:outline-none"
|
||||
@@ -77,7 +108,7 @@ export function ComposeBox({ onPublished }: { onPublished?: () => void }) {
|
||||
|
||||
<div className="flex items-center justify-between mt-1">
|
||||
<span className={`text-[10px] ${overLimit ? "text-danger" : "text-text-dim"}`}>
|
||||
{charCount > 0 && `${charCount}/280`}
|
||||
{uploading ? "uploading image…" : charCount > 0 ? `${charCount}/280` : ""}
|
||||
</span>
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="text-text-dim text-[10px]">Ctrl+Enter to post</span>
|
||||
|
||||
@@ -201,14 +201,16 @@ export function NoteCard({ event }: NoteCardProps) {
|
||||
>
|
||||
quote
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setShowZap(true)}
|
||||
className="text-[11px] text-text-dim hover:text-zap transition-colors"
|
||||
>
|
||||
{zapData && zapData.totalSats > 0
|
||||
? `⚡ ${zapData.totalSats.toLocaleString()} sats`
|
||||
: "⚡ zap"}
|
||||
</button>
|
||||
{(profile?.lud16 || profile?.lud06) && (
|
||||
<button
|
||||
onClick={() => setShowZap(true)}
|
||||
className="text-[11px] text-text-dim hover:text-zap transition-colors"
|
||||
>
|
||||
{zapData && zapData.totalSats > 0
|
||||
? `⚡ ${zapData.totalSats.toLocaleString()} sats`
|
||||
: "⚡ zap"}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user