Commit Graph
2005 Commits
Author SHA1 Message Date
jason5ng32andClaude Opus 5.5 b84a1d3764 Refactor(ip-infos): drop the default map images
A card only shows its map once location data has landed, so the bundled
placeholder maps were never meant to be seen, and their labels sat in one
language among many. An empty map URL now renders a same-sized muted box,
which also covers a payload with a country but no coordinates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 09:35:31 +08:00
jason5ng32andClaude Opus 5.5 6e40a611d3 Fix(api): require a tag-shaped language in the map proxy
Any non-empty language reached Static Maps, so every distinct value was an
uncached upstream call whose answer the edge kept for a year. A tag-shape
check still passes region-tagged UI locales (zh-TW, pt-BR) without an
allow-list, and the handler block now covers both sides.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 09:35:27 +08:00
Victor SolanoandClaude Opus 5.5 64ace80bf2 Fix(api): accept region-tagged languages in the map proxy (#506)
The UI passes its locale code as the map language, and pt-BR and zh-TW are
registered locales, but /api/map only accepted a bare two-letter code, so
every map request from those two locales answered 400 and the map never
loaded. Pass the tag through like every other ?lang (api/AGENTS.md) and
URL-encode it where the Static Maps URL is built, so the value stays one
query parameter.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 09:27:27 +08:00
jason5ng32andClaude Opus 5.5 79a91171f7 Refactor(probes): take chain options as an object and share version validators
runChain's optional originalSite / accept move into an options object, so a
chain that needs only one no longer passes an `undefined` placeholder.

The per-version validators become isValidIPv4 / isValidIPv6 in
common/valid-ip.js, next to isValidIP: the "Valid" prefix keeps them apart
from the non-validating isIPv6 discriminator.

Tests now run the four single-version entry points against a stubbed fetch,
so dropping or swapping a chain's validator fails the suite.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 23:28:12 +08:00
14649814andAntigravity f4d90fe44c Fix(probes): strictly validate IP version on dedicated v4/v6 chains (#504)
- Require isValidIP && isIPv6 on IPv6-only probes (ipChecking6, cloudflareV6)
- Require isValidIP && !isIPv6 on IPv4-only probes (ipChecking4, cloudflareV4)
- Export isIPv4 and isOnlyIPv6 and add dedicated unit tests in getips.test.js

Co-authored-by: Antigravity <antigravity@google.com>
2026-10-15 23:25:19 +08:00
jason5ng32 70c1cbd2b9 Merge branch 'sponsors-2026-10b' into dev 2026-10-14 18:02:07 +08:00
jason5ng32andClaude Opus 5.5 547e9a1e84 Docs(sponsors): add Proxy-Seller and link sponsor names
Proxy-Seller joins the paid sponsors in all six READMEs and the footer
acknowledgement list. Each sponsor's bold name in the description line now
links to the same destination as its logo, so the copy is clickable too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:01:52 +08:00
jason5ng32 5d378c5e13 Improvements 2026-10-13 09:54:52 +08:00
jason5ng32 47dff987b1 Improvements 2026-10-13 09:48:16 +08:00
jason5ng32 6036a7c570 Merge branch 'readme-supporters-layout' into dev 2026-10-11 10:41:18 +08:00
Jason Ng da9614c87e Merge pull request #502 from jason5ng32/readme-supporters-layout
Docs(sponsors): separate supporters and stack their logos
2026-10-11 10:41:06 +08:00
jason5ng32andClaude Opus 5.5 068ea5a795 Docs(sponsors): separate supporters and stack their logos
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 10:40:29 +08:00
Jason Ng 6211b124b0 Merge pull request #501 from jason5ng32/sponsors-2026-10
Docs(sponsors): add SwiftProxy and split paid sponsors from supporters
2026-10-10 10:25:35 +08:00
jason5ng32 e23f00a818 Merge branch 'sponsors-2026-10' into dev 2026-10-10 10:24:47 +08:00
jason5ng32andClaude Opus 5.5 2961d9ba8d Docs(sponsors): add SwiftProxy and split paid sponsors from supporters
The README listed every sponsor as an equal-size logo at the bottom, with
the only ad copy hidden in a hover-only title attribute. Paid sponsors now
get their own group with a visible one-line description under each logo;
free-plan supporters share one row of smaller logos. V.PS links carry the
README's locale in utm_content.

SwiftProxy joins the paid group and the footer acknowledgement list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 10:24:19 +08:00
jason5ng32 a509b99207 Improvements 2026-10-09 14:23:04 +08:00
jason5ng32 187ede91a9 Improvements 2026-10-07 15:34:08 +08:00
jason5ng32andClaude Opus 5.5 017e5c9af3 Feat(ip-infos): point score details to a live blocklist check
Score details is one of the most-opened panels, but the score is not a
live reading. A line under it links to Blocklist Check with the IP
carried as `?q=`, which the tool now prefills without running: the
visitor may be signed out or out of quota.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 15:26:02 +08:00
jason5ng32 117ebaa65a Improvements 2026-10-07 10:03:06 +08:00
jason5ng32andClaude Opus 5.5 89a103a3b7 Fix(footer): open the About sheet only on the page on screen
Home and ToolPage are both kept alive with a Footer each, so once a tool
page had been visited, a footer link on Home opened both sheets and the
cached one, stuck on its own tab, covered the right one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 00:45:35 +08:00
jason5ng32 6d7221538d Improvements 2026-10-06 13:03:58 +08:00
jason5ng32 8d7b53d1de Improvements 2026-10-06 11:35:36 +08:00
Jason Ng 015d6aef7b Merge pull request #500 from jason5ng32/feat/tools-as-pages
Feat/tools as pages
2026-10-06 11:31:09 +08:00
Claude de9d3d2118 Fix(service-status): drop a detail answer from before a reload
A detail request still in flight when the overview reloads (Refresh, or
the re-pull on activation) wrote its answer back after the reload had
cleared the cache, so the reopened card skipped its fetch and showed the
older snapshot. Reload bumps an epoch; an answer from an earlier one is
discarded.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-06 03:03:58 +00:00
Claude de6c5d730d Style: open PageBreadcrumb and UserMenu with their purpose comment
Their purpose was stated in <script setup>; it now opens the template as
in the rest of components/, with the script comment keeping only what
the markup does not say.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-06 02:59:39 +00:00
Claude f2d684faa8 Chore: document the ASN Profile graph's expand-to-drawer
The profile page keeps ASNConnectivity expandable; the guide, the host
card's comment and the prop's comment said otherwise.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-06 02:57:58 +00:00
Claude 26cb4ad15c Fix(breadcrumb): a section crumb stays a link at the end of the trail
Tool pages end their breadcrumb on Advanced Tools, as the <h1> beside it
names the tool. The crumb was rendered as the current page (aria-current,
not clickable) and its section ignored; now any crumb with a section links
to it, and only a bare last crumb is the current page.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-06 02:57:58 +00:00
Claude 7571e0c71e Fix(service-status): re-pull the overview when shown again after a backend cycle
The tool page is kept alive, so a visitor returning after the backend's
5-minute refresh saw the status pulled at mount until they hit Refresh.
On activation, an overview older than that cycle reloads as Refresh does.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-06 02:57:58 +00:00
Claude e39aed71e3 Fix(achievements): open the sheet when it mounts after the request
UserMenu raises the request from a tool, privacy or report page and goes
Home first. Home's Achievements is an async component: on a first visit it
can mount after the flag is already set, so the request was missed and the
flag stayed set, swallowing every later one. The watcher now runs
immediately and acts only on a raised flag.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-06 02:57:58 +00:00
jason5ng32 b616b7e00e Improvements 2026-10-06 10:48:50 +08:00
jason5ng32 8543879bbd Improvements 2026-10-06 10:33:31 +08:00
jason5ng32 78db2f8934 Improvements 2026-10-06 10:16:04 +08:00
Claude 4429020d91 Fix(nav): navigate from the mobile sheet after it has closed
WebKit records a page's back/forward snapshot as it navigates away,
so a tool or section picked from the mobile nav sheet left a snapshot
with the sheet still sliding out, which a swipe back then showed. The
sheet closes first and the navigation follows its slide-out.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-06 01:57:12 +00:00
Claude 3e4a268ce5 Fix(ui): resolve the route in Footer's setup
useRoute() inside the computed ran inject() outside setup, which
returns undefined: Footer threw on every render and the navigation
back to the homepage lost its scroll restore (the page landed at the
top). The route is resolved once in setup.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-06 01:45:51 +00:00
Claude 65ec652135 Refactor(auth): one auth domain per deployment
VITE_FIREBASE_AUTH_DOMAIN is each environment's own host, served by the
/__/auth proxy; the PWA-only VITE_FIREBASE_PWA_AUTH_DOMAIN and
utils/auth-domain.js go. Every OAuth provider lists the handler URL per
environment (Google and GitHub both take several redirect URIs).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-06 01:38:29 +00:00
Claude ebe2c36ae3 Fix(auth): offer GitHub sign-in in the installed PWA too
GitHub OAuth apps now take several redirect URIs, with optional
wildcard matching, so the PWA's own auth domain can be registered
there like Google's; the menu no longer hides GitHub when the PWA
signs in through a different domain (signInProvidersFor and the
store getter go). The operator notes name both registrations.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-05 17:04:44 +00:00
Claude 435d9f6413 Chore: drop dead nav locale keys, one isFireBaseSet, page-bg comment
nav.Title / PingTest / MTRTest / RuleTest had no reader in any locale.
The store takes isFireBaseSet from firebase-init.js instead of
recomputing it in checkFirebaseEnv(). The --page-bg comment no longer
claims index.html's colours must match it; they are tuned separately.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-05 17:02:50 +00:00
jason5ng32 ae52320d3b Improvements 2026-10-06 00:57:30 +08:00
Claude 96525d2fc7 Chore: trim the branch — leftovers, redundancy, comments
A pass over every file the branch touched, after the iOS animation hunt
left tries and reverts behind it. Removed what nothing reaches: the
view-transition rule for a transition no code starts, an unreachable
guard in the transition hook, a no-op KeepAlive key branch, a sign-in
guard the menu already enforces, usage-dialog wrappers that only
forwarded to the store, a duplicated modifier-click check and card
filter (isPlainClick / listedTools), a test that hand-rolled
listedTools, a drawer-era fixture parameter. auth-flow.js folded into
auth-redirect.js. Comments cut to what the code cannot say itself —
file headers of a few lines, the measured iOS reasons, non-obvious
orderings — and stale ones fixed (Nav under KeepAlive, Home.vue
reusing DEFAULT_META, "from Nav", enabledCards). AGENTS.md sections
tightened to the code as it is now.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-05 16:50:16 +00:00
Claude 47eca1a4f6 Chore(debug): remove the ?debug=nav overlay
The stall it was built to diagnose is fixed (utils/revive-animations.js);
the overlay, its App.vue gate and the event it listened to go.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-05 16:39:22 +00:00
Claude a4020442f0 Fix(ui): revive the page's CSS animations after a history step
On iOS, accelerated CSS animations running before a swipe-back stay
visually frozen once the gesture lands on the previous page: the frame
rate, the animations' own time and their iteration events all carry on,
but the compositor paints no new frame for them until their layer is
rebuilt (measured with the ?debug=nav overlay; cancel + play, a
display:none round trip or a re-insert revive them, ancestor style
changes do not). A push revives them as a side effect of its page
transition; a history step, where the browser's gesture replaces our
transition, does not. After every navigation that came from popstate,
utils/revive-animations.js cancels, replays and resets to its time each
running CSS animation, two frames after the DOM lands and again at
400ms and 1200ms in case the gesture snapshot is dismissed late.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-05 16:27:19 +00:00
Claude 2f27e62d19 Chore(debug): temporary ?debug=nav overlay for the iOS Nav animation stall
The Nav's CSS animations (Pulse's globe and ping) stall on iOS after a
swipe-back into the homepage, with KeepAlive and the page transitions
both ruled out and no WebKit available off the device. ?debug=nav
(kept in localStorage, ?debug=off clears) mounts widgets/NavDebug.vue:
live rAF rate, whether the ping animation's time advances and iterates,
reference CSS animations in a fixed panel and in the page flow, the
Nav's hidden state, a timeline of popstate (with hasUAVisualTransition)
/ route / visibility / focus / touch / scroll events, buttons that try
one candidate remedy at a time, and a Copy button for the log. Removed
once the cause is known.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-05 16:16:08 +00:00
Claude 563c55c6d8 Style: slide between pages with View Transitions
Route changes animate like native navigation: a tool page slides in
from the right, going home slides it back out, tool to tool cross-fades
— utils/page-transition.js decides the direction from the route pair
and wraps the router's DOM update in document.startViewTransition from
router/index.js, so the snapshot, the swap and the scroll restoration
happen before the animation and pages of different heights never
overlap. Nothing animates on a query-only change, under reduced motion,
on a history step the browser already animated (swipe-back), or in a
browser without the API; a navigation arriving mid-transition skips the
running one. The Nav opts out by view-transition-name and stays put
while the page moves.

Reapplied after the Nav's animation stall on iOS proved unrelated: it
reproduces with the transitions removed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-05 16:10:07 +00:00
Claude 34d69f8ec9 Fix(pwa): keep the iOS status bar opaque in the installed app
Since iOS 26 the system draws its Liquid Glass scroll-edge blur over
the top of a Home Screen web app whose page runs under the status bar,
which black-translucent asked for, and the blur covered the Nav. With
no apple-mobile-web-app-status-bar-style the status bar stays opaque
system chrome above the web view; the strip Nav.vue painted under a
translucent one goes with it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-05 16:06:07 +00:00
Claude fd9b042019 Revert(ui): drop the page transitions
Reverts the View Transitions hook-up, its keyframes, the Nav naming
and the two diagnostic follow-ups. On iOS the Nav's own animations
(Pulse's globe and ping) stalled after the forward transition and
stayed stalled after a swipe-back, while a transition back home
restored them — the capture of the fixed Nav is the suspect, and the
clean way to confirm it on the device is to run without any of it.

This reverts commits 2a360f0, d6d80da, 38a61fd, 156d0bf and 856f965.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-05 16:05:37 +00:00
Claude 2a360f0374 Fix(pwa): keep the status-bar strip hit-testable for iOS's edge blur check
iOS 26+ draws its scroll-edge blur over the top of a Home Screen web app
unless a hit test at the top edge finds a fixed, viewport-wide box with
a plain background colour (WebKit's LocalFrameView::fixedContainerEdges,
which honours pointer-events on its first pass). The safe-area strip is
exactly that box; it no longer opts out of hit testing.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-05 15:58:12 +00:00
Claude d6d80dac24 Chore(ui): device-side switch for page transitions
`?vt=off` turns the View Transitions off, `?vt=unnamed` keeps them but
leaves the Nav un-named (it slides with the page), `?vt=default`
restores the normal behaviour; the choice lives in localStorage. WebKit
cannot run in the sandbox and the Nav's animations stall on iOS after
a transition, so this is how the trigger gets bisected on the device.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-05 15:58:12 +00:00
Claude 38a61fdf92 Fix(ui): restart the Nav's animations after a page transition
WebKit leaves the accelerated CSS animations inside an element captured
under its own view-transition-name stalled once the transition is over:
after the first page transition Pulse's spinning globe and ping only
repainted in half-second jumps (measured frame by frame on iOS 26), and
a swipe back brought the stalled Nav home. Every transition now ends by
cancelling and replaying the running animations in the named elements
(restartAnimations in utils/page-transition.js), which recreates them
on the compositor.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-05 15:47:43 +00:00
Claude 1c7e7c68cd Fix(auth): give the installed PWA its own auth domain
VITE_FIREBASE_AUTH_DOMAIN stays the shared sign-in domain every browser
uses; the new optional VITE_FIREBASE_PWA_AUTH_DOMAIN is the domain the
installed PWA initialises Firebase with — the site's own host, served
by the /__/auth proxy, so the redirect handler runs inside the PWA
(utils/auth-domain.js). GitHub's OAuth app has one callback, on the
shared domain, so when the PWA domain differs the account menu offers
Google only. .env.example documents both and the console-side steps.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-05 15:28:57 +00:00
Claude 156d0bff1b Fix(ui): name the Nav for view transitions only while one runs
A view-transition-name makes an element a captured, separately
rendered group, and WebKit kept the Nav's own animations (Pulse's
spinning globe and ping) janky after an iOS swipe-back with the name
always on. The Nav and the status-bar tint now carry their names only
under html[data-page-transition], which the router hook sets before
the snapshot and clears when the transition finishes, so outside one
the Nav is an ordinary fixed element again.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-05 15:28:57 +00:00