diff --git a/src/components/SettingsViewer.tsx b/src/components/SettingsViewer.tsx
index e0da63a..9c95f10 100644
--- a/src/components/SettingsViewer.tsx
+++ b/src/components/SettingsViewer.tsx
@@ -9,7 +9,18 @@ import {
import { Switch } from "./ui/switch";
import { useSettings } from "@/hooks/useSettings";
import { useTheme } from "@/lib/themes";
-import { Palette, FileEdit, Heart, Trophy } from "lucide-react";
+import {
+ Palette,
+ FileEdit,
+ Heart,
+ HeartCrack,
+ Trophy,
+ Coffee,
+ Pizza,
+ Gift,
+ Star,
+ Crown,
+} from "lucide-react";
import { Button } from "./ui/button";
import { Progress } from "./ui/progress";
import { useLiveQuery } from "dexie-react-hooks";
@@ -61,14 +72,22 @@ export function SettingsViewer() {
return amount.toLocaleString();
}
- // Contribution tiers
- const contributionTiers = [210, 2100, 21000, 42000, 210000];
+ // Contribution tiers with icons
+ const contributionTiers = [
+ { amount: 210, icon: Coffee },
+ { amount: 2100, icon: Pizza },
+ { amount: 21000, icon: Gift },
+ { amount: 42000, icon: Heart },
+ { amount: 210000, icon: Star },
+ { amount: 1000000, icon: Crown },
+ ];
- function openSupportWindow() {
+ function openSupportWindow(amount: number) {
addWindow(
"zap",
{
recipientPubkey: GRIMOIRE_DONATE_PUBKEY,
+ defaultAmount: amount,
},
"Support Grimoire",
);
@@ -88,7 +107,11 @@ export function SettingsViewer() {
Post
-
+ {settings?.appearance?.showMonthlyGoal ? (
+
+ ) : (
+
+ )}
Support
@@ -189,12 +212,36 @@ export function SettingsViewer() {
Support Grimoire
- Help support development
+ Fund grimoire development
+ {/* Show Monthly Goal Toggle */}
+
+
+
+
+ Display donation progress in UI
+
+
+
+ updateSetting("appearance", "showMonthlyGoal", checked)
+ }
+ />
+
+
{/* Monthly Goal Progress */}
-
+
Monthly Goal
@@ -219,14 +266,18 @@ export function SettingsViewer() {
Contribute
- {contributionTiers.map((amount) => (
+ {contributionTiers.map(({ amount, icon: Icon }) => (
))}
diff --git a/src/components/ZapWindow.tsx b/src/components/ZapWindow.tsx
index 380f12b..d803f26 100644
--- a/src/components/ZapWindow.tsx
+++ b/src/components/ZapWindow.tsx
@@ -70,6 +70,8 @@ export interface ZapWindowProps {
customTags?: string[][];
/** Relays where the zap receipt should be published */
relays?: string[];
+ /** Optional default amount in sats to pre-select */
+ defaultAmount?: number;
}
// Default preset amounts in sats
@@ -99,6 +101,7 @@ export function ZapWindow({
onClose,
customTags,
relays: propsRelays,
+ defaultAmount,
}: ZapWindowProps) {
// Load event if we have a pointer - supports both EventPointer and AddressPointer
const event = useNostrEvent(eventPointer || addressPointer);
@@ -133,7 +136,9 @@ export function ZapWindow({
// Cache LNURL data for recipient's Lightning address
const { data: lnurlData } = useLnurlCache(recipientProfile?.lud16);
- const [selectedAmount, setSelectedAmount] = useState
(null);
+ const [selectedAmount, setSelectedAmount] = useState(
+ defaultAmount || null,
+ );
const [customAmount, setCustomAmount] = useState("");
const [isProcessing, setIsProcessing] = useState(false);
const [isPayingWithWallet, setIsPayingWithWallet] = useState(false);
diff --git a/src/components/nostr/user-menu.tsx b/src/components/nostr/user-menu.tsx
index 8d6806a..423f53e 100644
--- a/src/components/nostr/user-menu.tsx
+++ b/src/components/nostr/user-menu.tsx
@@ -49,6 +49,7 @@ import {
GRIMOIRE_LIGHTNING_ADDRESS,
} from "@/lib/grimoire-members";
import { MONTHLY_GOAL_SATS } from "@/services/supporters";
+import { useSettings } from "@/hooks/useSettings";
function UserAvatar({ pubkey }: { pubkey: string }) {
const profile = useProfile(pubkey);
@@ -83,6 +84,7 @@ export default function UserMenu() {
const account = use$(accounts.active$);
const { state, addWindow, disconnectNWC, toggleWalletBalancesBlur } =
useGrimoire();
+ const { settings } = useSettings();
const relays = state.activeAccount?.relays;
const blossomServers = state.activeAccount?.blossomServers;
const nwcConnection = state.nwcConnection;
@@ -494,29 +496,33 @@ export default function UserMenu() {
{/* Support Grimoire */}
-
-
-
-
- Support Grimoire
-
-
-
-
-
- {formatSats(monthlyDonations)}
-
- {" / "}
- {formatSats(MONTHLY_GOAL_SATS)}
-
-
- {goalProgress.toFixed(0)}%
-
-
-
+ {settings?.appearance?.showMonthlyGoal && (
+ <>
+
+
+
+
+ Support Grimoire
+
+
+
+
+
+ {formatSats(monthlyDonations)}
+
+ {" / "}
+ {formatSats(MONTHLY_GOAL_SATS)}
+
+
+ {goalProgress.toFixed(0)}%
+
+
+
+ >
+ )}
{/* Logout at bottom for logged in users */}
{account && (
diff --git a/src/lib/zap-parser.ts b/src/lib/zap-parser.ts
index 515a02d..cf53229 100644
--- a/src/lib/zap-parser.ts
+++ b/src/lib/zap-parser.ts
@@ -22,6 +22,8 @@ export interface ParsedZapCommand {
customTags?: string[][];
/** Relays where the zap receipt should be published */
relays?: string[];
+ /** Optional default amount in sats to pre-select */
+ defaultAmount?: number;
}
/**
@@ -33,6 +35,7 @@ export interface ParsedZapCommand {
* - `zap ` - Zap a specific person for a specific event
*
* Options:
+ * - `-a, --amount ` - Pre-select amount in sats
* - `-T, --tag [relay]` - Add custom tag (can be repeated)
* - `-r, --relay ` - Add relay for zap receipt publication (can be repeated)
*
@@ -53,12 +56,29 @@ export async function parseZapCommand(
const positionalArgs: string[] = [];
const customTags: string[][] = [];
const relays: string[] = [];
+ let defaultAmount: number | undefined;
let i = 0;
while (i < args.length) {
const arg = args[i];
- if (arg === "-T" || arg === "--tag") {
+ if (arg === "-a" || arg === "--amount") {
+ // Parse amount: -a
+ const amountStr = args[i + 1];
+ if (!amountStr) {
+ throw new Error("Amount option requires a value: -a ");
+ }
+
+ const amount = parseInt(amountStr, 10);
+ if (isNaN(amount) || amount <= 0) {
+ throw new Error(
+ `Invalid amount: ${amountStr}. Must be a positive number.`,
+ );
+ }
+
+ defaultAmount = amount;
+ i += 2;
+ } else if (arg === "-T" || arg === "--tag") {
// Parse tag: -T [relay-hint]
// Minimum 2 values after -T (type and value), optional relay hint
const tagType = args[i + 1];
@@ -122,7 +142,7 @@ export async function parseZapCommand(
const firstArg = positionalArgs[0];
const secondArg = positionalArgs[1];
- // Build result with optional custom tags and relays
+ // Build result with optional custom tags, relays, and amount
const buildResult = (
recipientPubkey: string,
pointer?: EventPointer | AddressPointer,
@@ -138,6 +158,7 @@ export async function parseZapCommand(
}
if (customTags.length > 0) result.customTags = customTags;
if (relays.length > 0) result.relays = relays;
+ if (defaultAmount !== undefined) result.defaultAmount = defaultAmount;
return result;
};
diff --git a/src/services/settings.ts b/src/services/settings.ts
index b0f45fa..629c30c 100644
--- a/src/services/settings.ts
+++ b/src/services/settings.ts
@@ -37,6 +37,8 @@ export interface AppearanceSettings {
animationsEnabled: boolean;
/** Accent color (hue value 0-360) */
accentHue: number;
+ /** Show monthly donation goal in UI (user menu, welcome page, settings) */
+ showMonthlyGoal: boolean;
}
/**
@@ -153,6 +155,7 @@ const DEFAULT_APPEARANCE_SETTINGS: AppearanceSettings = {
fontSizeMultiplier: 1.0,
animationsEnabled: true,
accentHue: 280, // Purple
+ showMonthlyGoal: true,
};
const DEFAULT_RELAY_SETTINGS: RelaySettings = {