app polish: hard-gate free trial + PixelVault-branded settings window#3
Merged
Conversation
A trial that never blocks converts no one, so once the 5 free anonymous uploads are used up we now STOP uploading and prompt sign-in (open the Account window) instead of nudging-and-continuing. - upload_and_notify returns Ok(None) when gated so callers don't show a false "Upload failed"; Ok(Some(url)) on a real upload. - Watcher keeps the clipboard image in place when gated (retry after sign-in); the per-image dedup avoids notification spam. - Signed-in users are unaffected (keyed uploads, no trial). Still client-side bypassable by design — it presents the wall, the server rate limiter is the real ceiling. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replaces the generic light/blue Tauri styling with PixelVault's design tokens (mirrors apps/web global.css): dark bg (#08090c), gold accent (#e4a44c), branded card/inputs/buttons. Window is now dark-only to match pixelvault.dev. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bump window height 540→640 and tighten vertical spacing so the account card + how-to + footer fit without a scrollbar. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Inline the transparent gold logo SVG above the title; bump height 640→700 and trim top padding so it still fits without scrolling. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The 'Free & open source · by PixelVault' line already links out, so the separate pixelvault.dev link was redundant. Height 700→650 to match. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…afety) Two-model review council (Claude + Codex) on the v0.2.0 diff. Fixes the 5 important findings: 1. Auth fail-open/split → unified cached Session (loaded once at startup, fail-CLOSED on real keychain errors vs. 'not found'); uploads read the cache, never the keychain. sign_out() now surfaces delete errors. A 401/403 on a keyed upload clears the session + prompts re-sign-in (UploadError::Unauthorized) instead of spamming raw error bodies. 2. Stale settings window → re-render on window focus (onFocusChanged), not just DOMContentLoaded. 3. Background-thread window mutation → open_settings() now runs show()/set_focus() via run_on_main_thread. 4. Non-atomic trial admission → try_reserve()/release()/commit_reserved() with a compare-exchange loop so concurrent watcher+capture uploads can't exceed 5. 5. Gated image never retried after sign-in → watcher tracks a separate gated_hash and lets the exact gated image through once signed in (no re-copy needed). cargo check + tsc/vite build green, no warnings. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Turns the 5-upload free trial into a real gate. Previously it was a soft nudge that kept uploading after the limit — which means users never had a reason to sign in (the funnel never closed).
Change
Once the 5 free anonymous uploads are used up, further anonymous uploads are blocked: the app shows a "Sign in to keep uploading" notification, opens the Account window, and does not put a URL on the clipboard. Signing in (keyed uploads) removes the limit.
upload_and_notifynow returnsOk(None)when gated so the watcher/capture callers don't surface a false "Upload failed";Ok(Some(url))on a real upload.Still client-side bypassable by design (reinstall resets the counter) — it presents the wall for the typical user; the server-side anonymous rate limiter remains the real abuse ceiling.
Verified compiling via
tauri dev(full build green).🤖 Generated with Claude Code