893de0a2c330
feat: wire feedback form to Web3Forms (temporary, pre-Vesper) (v3.6.62)
- time
- 2026-05-20 11:18 UTC · 5 months ago
- machine
- koh2
- parent
- a0f34330d095
↓ peach-browser-893de0a2.tar.gzatlas at this save
files changed3 files
manifest.firefox.json+1 −1manifest.json+1 −1src/popup/views/Settings.tsx+41 −35manifest.firefox.json+1 −1
@@ -2,7 +2,7 @@22 "_comment_audio_capture": "Firefox does not honor the Chrome 'audioCapture' optional_permission — getUserMedia in WebExtensions is gated solely by the runtime permission prompt. Microphone access for chirp pairing works from the popup under the existing '<all_urls>' host permission; no manifest entry is required or accepted here.",33 "manifest_version": 3,44 "name": "Peach",5- "version": "3.6.61",5+ "version": "3.6.62",66 "description": "Zero-knowledge password manager",77 "browser_specific_settings": {88 "gecko": {manifest.json+1 −1
@@ -1,7 +1,7 @@11 {22 "manifest_version": 3,33 "name": "Peach",4- "version": "3.6.61",4+ "version": "3.6.62",55 "description": "Zero-knowledge password manager",66 "action": {77 "default_popup": "src/popup/index.html",src/popup/views/Settings.tsx+41 −35
@@ -1,4 +1,4 @@1-import { createEffect, createMemo, createSignal, For, onMount, Show } from "solid-js";1+import { createEffect, createMemo, createSignal, For, Match, onMount, Show, Switch } from "solid-js";22 import { sendMessage } from "../App";33 import { PeachMark } from "../components/PeachMark";44 import { StackDeck } from "../components/settings/StackDeck";@@ -22,6 +22,7 @@2222 type ShortcutAction,2323 } from "../../shared/shortcuts";2424 import { isNativePlatform, nativePlugin } from "../../shared/native";25+import { WEB3FORMS_KEY } from "../../shared/config";2526 2627 interface LicenseInfo {2728 valid: boolean;@@ -285,8 +286,8 @@285286 286287 const [fbCategory, setFbCategory] = createSignal("Bug report");287288 const [fbMessage, setFbMessage] = createSignal("");288- const [fbSubmitting, setFbSubmitting] = createSignal(false);289- const [fbResult, setFbResult] = createSignal<"success" | "error" | null>(null);289+ type FeedbackState = 'idle' | 'sending' | 'sent' | 'error';290+ const [feedbackState, setFeedbackState] = createSignal<FeedbackState>('idle');290291 291292 createEffect(() => {292293 if (props.upgradeHighlight) {@@ -576,25 +577,36 @@576577 }577578 578579 async function handleSubmitFeedback() {579- if (!fbMessage().trim() || fbSubmitting()) return;580- setFbSubmitting(true);581- setFbResult(null);582- const res = await sendMessage({583- type: "SUBMIT_FEEDBACK",584- payload: {585- category: fbCategory(),586- message: fbMessage().trim(),587- version,588- browser: navigator.userAgent,589- },590- }) as { ok: boolean; error?: string };591- setFbSubmitting(false);592- if (res.ok) {593- setFbResult("success");594- setFbMessage("");595- setTimeout(() => setFbResult(null), 4000);596- } else {597- setFbResult("error");580+ if (!fbMessage().trim()) return;581+582+ setFeedbackState('sending');583+584+ try {585+ const res = await fetch('https://api.web3forms.com/submit', {586+ method: 'POST',587+ headers: { 'Content-Type': 'application/json' },588+ body: JSON.stringify({589+ access_key: WEB3FORMS_KEY,590+ subject: `Peach Feedback — ${fbCategory()}`,591+ message: fbMessage(),592+ from_name: 'Peach User',593+ // Honeypot — leave blank594+ botcheck: '',595+ }),596+ });597+598+ if (!res.ok) throw new Error(`HTTP ${res.status}`);599+ const data = await res.json() as { success: boolean; message?: string };600+ if (!data.success) throw new Error(data.message ?? 'unknown error');601+602+ setFeedbackState('sent');603+ setFbMessage('');604+ setFbCategory(FEEDBACK_CATEGORIES[0]);605+ setTimeout(() => setFeedbackState('idle'), 4000);606+ } catch (err) {607+ console.error('[feedback]', err);608+ setFeedbackState('error');609+ setTimeout(() => setFeedbackState('idle'), 4000);598610 }599611 }600612 @@ -1707,23 +1719,17 @@17071719 Version {version} · will be included automatically17081720 </p>17091721 1710- <Show when={fbResult() === "success"}>1711- <p class="peach-feedback-result peach-feedback-result--ok">1712- Sent — thank you1713- </p>1714- </Show>1715- <Show when={fbResult() === "error"}>1716- <p class="peach-feedback-result peach-feedback-result--err">1717- Failed to send — try again1718- </p>1719- </Show>1720-17211722 <button17221723 class="peach-btn peach-btn--accent peach-btn--sm peach-feedback-submit"1724+ disabled={!fbMessage().trim() || feedbackState() === 'sending'}17231725 onClick={() => void handleSubmitFeedback()}1724- disabled={fbSubmitting() || !fbMessage().trim()}17251726 >1726- {fbSubmitting() ? "Sending..." : "Send feedback"}1727+ <Switch>1728+ <Match when={feedbackState() === 'idle'}>Send</Match>1729+ <Match when={feedbackState() === 'sending'}>Sending…</Match>1730+ <Match when={feedbackState() === 'sent'}>Sent ✓</Match>1731+ <Match when={feedbackState() === 'error'}>Failed — try again</Match>1732+ </Switch>17271733 </button>17281734 17291735 <p class="peach-feedback-anon">