Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
415 changes: 249 additions & 166 deletions Sources/VPNBypassCore/MenuBarViews.swift

Large diffs are not rendered by default.

11 changes: 9 additions & 2 deletions Sources/VPNBypassCore/Resources/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
"Clear" = "Clear";
"Verify Routes" = "Verify Routes";
"Verifying..." = "Verifying...";
"Active Services" = "Active Services";
"No services enabled" = "No services enabled";
"+%lld more" = "+%lld more";
"+ %lld more" = "+ %lld more";
"Active Routes" = "Active Routes";
Expand Down Expand Up @@ -357,6 +355,15 @@
"Your listed domains and services become editable rules you can send through any route (a proxy, a Tailscale peer, or a specific VPN). You can switch back anytime." = "Your listed domains and services become editable rules you can send through any route (a proxy, a Tailscale peer, or a specific VPN). You can switch back anytime.";
"Switch to your per-rule custom routing. You can switch back to a simple mode anytime." = "Switch to your per-rule custom routing. You can switch back to a simple mode anytime.";

/* ===== Menu bar: what is routed, by what the user added ===== */
"Skipping the VPN" = "Skipping the VPN";
"Through the VPN" = "Through the VPN";
"Routed by your rules" = "Routed by your rules";
"no routes" = "no routes";
"Left from earlier" = "Left from earlier";
"Everything else" = "Everything else";
"direct" = "direct";

/* ===== Settings: undo after a delete or a Turn All On/Off ===== */
"Undo" = "Undo";
"Removed %@." = "Removed %@.";
Expand Down
11 changes: 9 additions & 2 deletions Sources/VPNBypassCore/Resources/es.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
"Clear" = "Limpiar";
"Verify Routes" = "Verificar rutas";
"Verifying..." = "Verificando...";
"Active Services" = "Servicios activos";
"No services enabled" = "Ningún servicio habilitado";
"+%lld more" = "+%lld más";
"+ %lld more" = "+ %lld más";
"Active Routes" = "Rutas activas";
Expand Down Expand Up @@ -357,6 +355,15 @@
"Your listed domains and services become editable rules you can send through any route (a proxy, a Tailscale peer, or a specific VPN). You can switch back anytime." = "Tus dominios y servicios pasan a ser reglas editables que puedes enviar por cualquier ruta (un proxy, un equipo de Tailscale o una VPN concreta). Puedes volver cuando quieras.";
"Switch to your per-rule custom routing. You can switch back to a simple mode anytime." = "Pasa a tu enrutamiento personalizado por reglas. Puedes volver a un modo simple cuando quieras.";

/* ===== Menu bar: what is routed, by what the user added ===== */
"Skipping the VPN" = "Sin pasar por la VPN";
"Through the VPN" = "Por la VPN";
"Routed by your rules" = "Enrutado por tus reglas";
"no routes" = "sin rutas";
"Left from earlier" = "Restos de antes";
"Everything else" = "Todo lo demás";
"direct" = "directo";

/* ===== Ajustes: deshacer tras quitar algo o tras Activar/Desactivar todos ===== */
"Undo" = "Deshacer";
"Removed %@." = "Se quitó %@.";
Expand Down
11 changes: 9 additions & 2 deletions Sources/VPNBypassCore/Resources/fr.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
"Clear" = "Effacer";
"Verify Routes" = "Vérifier les routes";
"Verifying..." = "Vérification...";
"Active Services" = "Services actifs";
"No services enabled" = "Aucun service activé";
"+%lld more" = "+%lld de plus";
"+ %lld more" = "+ %lld de plus";
"Active Routes" = "Routes actives";
Expand Down Expand Up @@ -357,6 +355,15 @@
"Your listed domains and services become editable rules you can send through any route (a proxy, a Tailscale peer, or a specific VPN). You can switch back anytime." = "Vos domaines et services deviennent des règles modifiables que vous pouvez envoyer par n'importe quelle route (un proxy, un pair Tailscale ou un VPN précis). Vous pouvez revenir en arrière à tout moment.";
"Switch to your per-rule custom routing. You can switch back to a simple mode anytime." = "Passez à votre routage personnalisé par règles. Vous pouvez revenir à un mode simple à tout moment.";

/* ===== Menu bar: what is routed, by what the user added ===== */
"Skipping the VPN" = "Hors du VPN";
"Through the VPN" = "Par le VPN";
"Routed by your rules" = "Routé par vos règles";
"no routes" = "aucune route";
"Left from earlier" = "Restes d'avant";
"Everything else" = "Tout le reste";
"direct" = "en direct";

/* ===== Réglages : annuler après une suppression ou un Tout activer/désactiver ===== */
"Undo" = "Annuler";
"Removed %@." = "%@ supprimé.";
Expand Down
295 changes: 295 additions & 0 deletions Tests/VPNBypassTests/RoutedBySourceTests.swift

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **With two VPNs running, the app could pick the wrong one.** Several tunnels being up at once is ordinary — a corporate VPN alongside Tailscale — but the app took the first one it happened to see, which had nothing to do with which tunnel was carrying traffic. Because Tailscale usually appears earlier in that list, it could win, and in VPN Only mode the app would then install its rules to escape the wrong tunnel and send the other one's traffic straight out. It now prefers the tunnel actually carrying the default route, never picks Tailscale, keeps its choice stable while several remain valid, and breaks any remaining tie the same way every time.

### Changed
- **The dropdown lists what is routed by what you added, not by address.** It showed your services as chips, then Active Routes as raw addresses, the first four that happened to sort first and then "+ 58 more". Telegram showed up twice, once as a chip and again as two address ranges. In VPN Only mode four of the six rows were the app's own catch-all routes, and the count included them. The two cards are now one list, Skipping the VPN in Bypass and Through the VPN in VPN Only, with one row per service, domain or IP range you have on, in the order Settings lists them, and its route count ("Telegram, 12 routes"). The header gives the total. Hover over a row to see its addresses. An entry that has no routes while nothing is applying or waiting to apply gets an amber mark and "no routes". In VPN Only the catch-all routes are one line, "Everything else: direct", and the count leaves them out. Routes that no entry owns, such as those of an entry you just removed while they wait to be cleaned up, are one "Left from earlier" line. Custom mode lists its rules that installed a route, under Routed by your rules. The new text is in English, Spanish and French. How routes are applied has not changed.
- **Deletes and Turn All On/Off in Settings can be undone.** Every trash button removed its domain, custom service, rule or route on the first click with no way back, and a custom service took its whole domain list with it. All turned on every service at once, so 33 services could leave the VPN in one click, and None was red like a delete though it only switched things off. A delete now leaves a line in the list ("Removed Work Tools and its 5 domains.") with an Undo button, and Edit > Undo (⌘Z) does the same. Undo puts the entry back in its place with its switch as it was, through the same code as adding it, so its routes come back too. All and None are now Turn All On and Turn All Off in a ⋯ menu, on the Domains and Services pages, and they leave the same line. Turn All On for services asks first when it would turn on more than five ("Send 33 services around the VPN?"), with Cancel as the default button. The new text is in English, Spanish and French.
- **The Services page lists the services that are on first.** The 37 built-in services sat in one fixed order, so the ones you had on were spread through the list, often below the fold. They now sit in an On section at the top, custom ones included. The rest follow in the usual order under Custom Services and Built-in Services, and each header gives its count. A switch you flip on the page keeps its row where it is until you next open the page. All and None re-sort the list at once. Search filters every section. The headers are in English, Spanish and French.
- **In Settings, the routing mode no longer looks like a page button.** The three modes sat above the page buttons in the same green pills, so a click meant to open the VPN Only list asked to switch the whole Mac. The page buttons are now a toolbar under the title bar, with the icon above the label and a plain highlight on the page shown. The mode is a menu at the right end of the title bar that reads "Mode Bypass" and checks the mode in use; on macOS 14.4 and later each mode has a short line under its name. Picking another mode opens a sheet that lists the three modes, with one sentence each and what your lists hold for it ("4 services and 2 domains", "3 entries", or "Your lists become rules" before the first switch to Custom). Nothing changes until Switch, which goes through the same mode switch as before. The sheet and the menu are in English, Spanish and French.
Expand Down
2 changes: 1 addition & 1 deletion docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Switch on a service there, or type a site into the field and press Return. "All

- the pill reads ON;
- the menu bar mark shows its arrow head (it is two plain lines and a bar while nothing is routed);
- the question gives way to the normal dropdown, and the service or domain appears under Active Services or Active Routes.
- the question gives way to the normal dropdown, and the service or domain appears under Skipping the VPN with its route count.

If the pill reads NOT ENFORCING, the helper is not running; Settings > General shows its state and a Reinstall button. If macOS says the app is damaged, see [Troubleshooting](troubleshooting.md#app-wont-open-damaged-error-macos-gatekeeper).

Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Corporate VPN clients send everything through the tunnel, so streaming stalls, A

## The menu bar app

Everything lives in the dropdown: the VPN it found, a pill that says whether routes are enforced, the Mode switch, a field to add a domain, and the services and routes in use. Settings opens from the gear at its foot. See [Usage](usage.md).
Everything lives in the dropdown: the VPN it found, a pill that says whether routes are enforced, the Mode switch, a field to add a domain, and what is routed, one row per service or domain you added. Settings opens from the gear at its foot. See [Usage](usage.md).

<div class="vb-gallery" markdown>
<figure markdown>
Expand Down
2 changes: 1 addition & 1 deletion docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Click the VPN Bypass mark in the menu bar: two lines and a bar, with an arrow he
- on a fresh install in Bypass mode, in place of everything down to the gear: the question "What should skip the VPN?", six common services with their switches, a row that opens Settings on the Services page, a field to add a site, and a line that offers VPN Only. Once a service is on or a site is on the list, the normal dropdown below takes its place at once;
- the Mode control, with Bypass, VPN Only and Custom in every mode. Picking another mode asks first, and the selection moves only after you confirm. Entering Custom turns your lists into rules here too;
- a field to add a domain to the current mode's list;
- the active services and routes;
- what your lists route, one row per service, domain or IP range you added, with its route count, under Skipping the VPN in Bypass or Through the VPN in VPN Only. Hover over a row to see its addresses. A row that has no routes while no apply is running or waiting after a reconnect gets an amber mark. In VPN Only the app's own catch-all routes are one line, "Everything else: direct", and the count leaves them out. In Custom mode, Routes In Use comes first, then Routed by your rules lists the rules that installed a route. Routes that no entry on your lists owns, such as those of an entry you just removed, are one "Left from earlier" line;
- Refresh Routes, a Verify Routes icon, and a "…" menu with Verify Routes, Re-resolve DNS Now and Remove All Routes…, which asks before it removes anything;
- one line under the buttons with the result of the last apply, for example "62 routes applied 23 s ago, none failed";
- the gear that opens Settings.
Expand Down
Loading