mirror of
https://github.com/hoornet/vega.git
synced 2026-06-29 21:52:08 -07:00
Polish pass 6 + fix V4V auto-streaming not stopping on manual toggle
Polish: - ArticleEditor: sentence case on all buttons (← Drafts, Write, Preview, Zen, Meta, Publish, ← Back, New draft) - EditProfileForm: Save profile / Saving… / Saved ✓ - ImageField: Upload / Uploading… - RelaysView: Add, Publish list, Remove dead, Discover relays (sentence case) - InlineReplyBox: attachment remove x → ×, aria-labels on remove/attach/emoji Bug fix: - V4VIndicator: add userDisabledRef so manually turning off streaming prevents auto-start from re-engaging on subsequent play/pause/seek events for the same episode; resets automatically on new episode - V4VIndicator: remaining amber-* colors → zap theme token
This commit is contained in:
@@ -284,7 +284,7 @@ export function ArticleEditor() {
|
||||
<header className="border-b border-border px-4 py-2.5 flex items-center justify-between shrink-0">
|
||||
<div className="flex items-center gap-3">
|
||||
<button onClick={() => setActiveDraft(null)} className="text-text-dim hover:text-text text-[11px] transition-colors">
|
||||
← drafts
|
||||
← Drafts
|
||||
</button>
|
||||
<span className="text-text-dim text-[10px]">{wordCount > 0 ? `${wordCount} words` : "New article"}</span>
|
||||
{activeDraft && !published && lastSaved && (
|
||||
@@ -310,13 +310,13 @@ export function ArticleEditor() {
|
||||
onClick={() => setMode("write")}
|
||||
className={`px-3 py-1 transition-colors ${mode === "write" ? "bg-accent/10 text-accent" : "text-text-muted hover:text-text"}`}
|
||||
>
|
||||
write
|
||||
Write
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setMode("preview")}
|
||||
className={`px-3 py-1 transition-colors ${mode === "preview" ? "bg-accent/10 text-accent" : "text-text-muted hover:text-text"}`}
|
||||
>
|
||||
preview
|
||||
Preview
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -325,14 +325,14 @@ export function ArticleEditor() {
|
||||
className="px-3 py-1 text-[11px] border border-border text-text-muted hover:text-text transition-colors"
|
||||
title="Focus mode (F11)"
|
||||
>
|
||||
zen
|
||||
Zen
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => setShowMeta((v) => !v)}
|
||||
className={`px-3 py-1 text-[11px] border border-border transition-colors ${showMeta ? "text-accent border-accent/40" : "text-text-muted hover:text-text"}`}
|
||||
>
|
||||
meta
|
||||
Meta
|
||||
</button>
|
||||
|
||||
<button
|
||||
@@ -340,7 +340,7 @@ export function ArticleEditor() {
|
||||
disabled={!canPublish || publishing || published}
|
||||
className="px-4 py-1 text-[11px] bg-accent hover:bg-accent-hover text-accent-text transition-colors disabled:opacity-30 disabled:cursor-not-allowed"
|
||||
>
|
||||
{published ? "published ✓" : publishing ? "publishing…" : "publish"}
|
||||
{published ? "Published ✓" : publishing ? "Publishing…" : "Publish"}
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
@@ -497,7 +497,7 @@ function DraftListView({ onNewDraft }: { onNewDraft: () => void }) {
|
||||
<header className="border-b border-border px-4 py-2.5 flex items-center justify-between shrink-0">
|
||||
<div className="flex items-center gap-3">
|
||||
<button onClick={goBack} className="text-text-dim hover:text-text text-[11px] transition-colors">
|
||||
← back
|
||||
← Back
|
||||
</button>
|
||||
<h2 className="text-text text-[13px] font-medium">Drafts</h2>
|
||||
<span className="text-text-dim text-[11px]">{drafts.length} {drafts.length === 1 ? "draft" : "drafts"}</span>
|
||||
@@ -506,7 +506,7 @@ function DraftListView({ onNewDraft }: { onNewDraft: () => void }) {
|
||||
onClick={onNewDraft}
|
||||
className="px-3 py-1 text-[11px] bg-accent hover:bg-accent-hover text-accent-text transition-colors"
|
||||
>
|
||||
new draft
|
||||
New draft
|
||||
</button>
|
||||
</header>
|
||||
|
||||
@@ -515,7 +515,7 @@ function DraftListView({ onNewDraft }: { onNewDraft: () => void }) {
|
||||
<div className="px-4 py-12 text-center space-y-2">
|
||||
<p className="text-text-dim text-[13px]">No drafts yet.</p>
|
||||
<p className="text-text-dim text-[11px] opacity-60">
|
||||
Click "new draft" to start writing an article.
|
||||
Click "New draft" to start writing an article.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -184,8 +184,9 @@ export function InlineReplyBox({ event, name, rootEvent }: InlineReplyBoxProps)
|
||||
onClick={() => removeAttachment(i)}
|
||||
className="absolute -top-1.5 -right-1.5 w-4 h-4 bg-danger text-accent-text text-[10px] rounded-full flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity"
|
||||
title="Remove"
|
||||
aria-label="Remove attachment"
|
||||
>
|
||||
x
|
||||
×
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
@@ -205,6 +206,7 @@ export function InlineReplyBox({ event, name, rootEvent }: InlineReplyBoxProps)
|
||||
onClick={handleFilePicker}
|
||||
disabled={uploading}
|
||||
title="Attach image or video"
|
||||
aria-label="Attach image or video"
|
||||
className="text-text-dim hover:text-text text-[16px] transition-colors disabled:opacity-30"
|
||||
>
|
||||
+
|
||||
@@ -213,6 +215,7 @@ export function InlineReplyBox({ event, name, rootEvent }: InlineReplyBoxProps)
|
||||
<button
|
||||
onClick={() => setShowReplyEmoji((v) => !v)}
|
||||
title="Insert emoji"
|
||||
aria-label="Insert emoji"
|
||||
className="text-text-dim hover:text-text text-[16px] transition-colors"
|
||||
>
|
||||
☺
|
||||
|
||||
@@ -23,6 +23,10 @@ export function V4VIndicator() {
|
||||
const playbackState = usePodcastStore((s) => s.playbackState);
|
||||
const { setV4VEnabled, setV4VStreaming, addStreamedSats } = usePodcastStore.getState();
|
||||
|
||||
// Tracks when the user explicitly turned off streaming mid-episode.
|
||||
// Prevents the auto-start effect from re-engaging until a new episode loads.
|
||||
const userDisabledRef = useRef(false);
|
||||
|
||||
const autoEnabled = useV4VStore((s) => s.autoEnabled);
|
||||
const defaultRate = useV4VStore((s) => s.defaultRate);
|
||||
const capReachedReason = useV4VStore((s) => s.capReachedReason);
|
||||
@@ -31,6 +35,11 @@ export function V4VIndicator() {
|
||||
const hasWallet = !!nwcUri;
|
||||
const hasRecipients = episode?.value && episode.value.length > 0;
|
||||
|
||||
// Reset user-disabled flag when a new episode loads
|
||||
useEffect(() => {
|
||||
userDisabledRef.current = false;
|
||||
}, [episode?.guid]);
|
||||
|
||||
// Auto-start streaming when autoEnabled and V4V episode starts playing
|
||||
useEffect(() => {
|
||||
if (
|
||||
@@ -39,6 +48,7 @@ export function V4VIndicator() {
|
||||
hasRecipients &&
|
||||
hasWallet &&
|
||||
!v4vStreaming &&
|
||||
!userDisabledRef.current &&
|
||||
episode
|
||||
) {
|
||||
const intervalId = startStreaming(
|
||||
@@ -77,10 +87,12 @@ export function V4VIndicator() {
|
||||
if (!episode || !hasWallet) return;
|
||||
|
||||
if (v4vStreaming) {
|
||||
userDisabledRef.current = true;
|
||||
stopStreaming();
|
||||
setV4VStreaming(false);
|
||||
setV4VEnabled(false);
|
||||
} else {
|
||||
userDisabledRef.current = false;
|
||||
const rate = autoEnabled ? defaultRate : v4vSatsPerMinute;
|
||||
const intervalId = startStreaming(
|
||||
episode,
|
||||
@@ -116,9 +128,9 @@ export function V4VIndicator() {
|
||||
capReachedReason
|
||||
? "text-text-dim bg-border/50"
|
||||
: v4vStreaming
|
||||
? "text-amber-400 bg-amber-500/10 animate-pulse"
|
||||
? "text-zap bg-zap/10 animate-pulse"
|
||||
: hasRecipients
|
||||
? "text-amber-400 bg-amber-500/10 hover:bg-amber-500/20"
|
||||
? "text-zap bg-zap/10 hover:bg-zap/20"
|
||||
: "text-text-dim hover:text-text"
|
||||
}`}
|
||||
title="Value 4 Value"
|
||||
|
||||
@@ -89,7 +89,7 @@ export function EditProfileForm({ pubkey, onSaved }: { pubkey: string; onSaved:
|
||||
disabled={saving || saved}
|
||||
className="px-4 py-1.5 text-[11px] bg-accent hover:bg-accent-hover text-accent-text transition-colors disabled:opacity-30 disabled:cursor-not-allowed"
|
||||
>
|
||||
{saved ? "saved ✓" : saving ? "saving…" : "save profile"}
|
||||
{saved ? "Saved ✓" : saving ? "Saving…" : "Save profile"}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -40,7 +40,7 @@ export function ImageField({ label, value, onChange }: { label: string; value: s
|
||||
className="px-2 py-1.5 text-[10px] border border-border text-text-dim hover:text-accent hover:border-accent/40 transition-colors disabled:opacity-40 disabled:cursor-not-allowed shrink-0"
|
||||
title="Upload from your computer"
|
||||
>
|
||||
{uploading ? "uploading…" : "upload"}
|
||||
{uploading ? "Uploading…" : "Upload"}
|
||||
</button>
|
||||
</div>
|
||||
{uploadError && <p className="text-danger text-[10px] mt-1">{uploadError}</p>}
|
||||
|
||||
@@ -277,7 +277,7 @@ export function RelaysView() {
|
||||
onClick={handleAddRelay}
|
||||
className="px-3 py-1.5 text-[11px] border border-border text-text-muted hover:text-accent hover:border-accent/40 transition-colors shrink-0"
|
||||
>
|
||||
add
|
||||
Add
|
||||
</button>
|
||||
{loggedIn && !!getNDK().signer && (
|
||||
<button
|
||||
@@ -285,7 +285,7 @@ export function RelaysView() {
|
||||
disabled={republishing}
|
||||
className="px-3 py-1.5 text-[11px] border border-border text-text-muted hover:text-accent hover:border-accent/40 transition-colors disabled:opacity-40 shrink-0"
|
||||
>
|
||||
{republishing ? "publishing…" : "publish list"}
|
||||
{republishing ? "Publishing…" : "Publish list"}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
@@ -303,7 +303,7 @@ export function RelaysView() {
|
||||
disabled={removing}
|
||||
className="px-3 py-1 text-[11px] border border-danger/30 text-danger hover:bg-danger/10 transition-colors disabled:opacity-40"
|
||||
>
|
||||
{removing ? "removing…" : "remove dead"}
|
||||
{removing ? "Removing…" : "Remove dead"}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
@@ -384,9 +384,9 @@ function SuggestedRelays() {
|
||||
{loading ? (
|
||||
<span className="inline-flex items-center gap-1">
|
||||
<span className="w-3 h-3 border border-accent border-t-transparent rounded-full animate-spin" />
|
||||
discovering…
|
||||
Discovering…
|
||||
</span>
|
||||
) : "discover relays"}
|
||||
) : "Discover relays"}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user