diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1a8fef6..6d868c6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,15 +7,13 @@ on: env: WAILS_VERSION: v3.0.0-alpha2.117 -# Runners are Blacksmith. The cache actions below are the upstream ones on -# purpose: Blacksmith intercepts them and serves from a colocated cache, and its -# own useblacksmith/* forks are archived. +# Runners are GitHub-hosted. jobs: macos: name: macOS (universal .dmg) # Apple Silicon; the universal build compiles arm64 and amd64 then lipos - # them together, so the extra cores pay for themselves here. - runs-on: blacksmith-12vcpu-macos-15 + # them together. + runs-on: macos-15 steps: - uses: actions/checkout@v4 @@ -56,7 +54,7 @@ jobs: linux: name: Linux (.deb / .rpm / .AppImage) - runs-on: nugget-linux + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 @@ -116,9 +114,7 @@ jobs: windows: name: Windows (installer) - # Blacksmith's Windows runners are in public beta; swap back to - # `windows-latest` if this job turns flaky. - runs-on: windows-pc + runs-on: windows-2025 steps: - uses: actions/checkout@v4 @@ -149,9 +145,9 @@ jobs: run: go install github.com/wailsapp/wails/v3/cmd/wails3@${{ env.WAILS_VERSION }} - name: Install NSIS - # The installer is built with makensis, which the Blacksmith Windows - # image does not ship (GitHub's older Windows images did). Chocolatey - # when the image has it, otherwise the official zip. + # The installer is built with makensis, which the windows-2025 image + # does not ship (GitHub's older Windows images did). Chocolatey when + # the image has it, otherwise the official zip. shell: pwsh run: | if (Get-Command makensis -ErrorAction SilentlyContinue) { @@ -198,7 +194,7 @@ jobs: android: name: Android (.apk) - runs-on: nugget-linux + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 @@ -282,7 +278,7 @@ jobs: publish: name: Publish release needs: [macos, linux, windows, android] - runs-on: nugget-linux + runs-on: ubuntu-24.04 permissions: contents: write steps: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 816818d..42fd232 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,9 +19,7 @@ env: SING_BOX_TAGS: with_gvisor,with_quic,with_wireguard,with_utls,with_clash_api,with_dhcp,with_acme WAILS_VERSION: v3.0.0-alpha2.117 -# Runners are Blacksmith. Note the cache actions below are the upstream ones on -# purpose: Blacksmith intercepts them and serves from a colocated cache, and its -# own useblacksmith/* forks are archived. +# Runners are GitHub-hosted. jobs: test: name: Go tests (${{ matrix.name }}) @@ -30,11 +28,11 @@ jobs: matrix: include: - name: linux - runner: nugget-linux + runner: ubuntu-24.04 - name: macos - runner: blacksmith-6vcpu-macos-15 + runner: macos-15 - name: windows - runner: windows-pc + runner: windows-2025 runs-on: ${{ matrix.runner }} steps: - uses: actions/checkout@v4 @@ -69,7 +67,7 @@ jobs: android: name: Build (android) - runs-on: nugget-linux + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 @@ -149,11 +147,11 @@ jobs: matrix: include: - name: macos-arm64 - runner: blacksmith-12vcpu-macos-15 + runner: macos-15 - name: linux-amd64 - runner: nugget-linux + runner: ubuntu-24.04 - name: windows-amd64 - runner: windows-pc + runner: windows-2025 runs-on: ${{ matrix.runner }} steps: - uses: actions/checkout@v4 diff --git a/frontend/src/App.css b/frontend/src/App.css index e101f3e..6751a86 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -194,6 +194,15 @@ --status-connected: oklch(var(--brand-l) var(--brand-c) var(--brand-h)); --status-error: oklch(0.55 0.225 27.325); + /* Categorical chart hues, in fixed order; checked for colour-blind separation. */ + --series-1: #2a78d6; + --series-2: #eb6834; + --series-3: #1baf7a; + --series-4: #eda100; + --series-5: #e87ba4; + --series-6: #008300; + --series-7: #4a3aa7; + --routing-apps: oklch(0.6 0.2 350); --routing-domains: oklch(0.53 0.2 300); --routing-ip: oklch(0.6 0.16 40); @@ -258,6 +267,14 @@ --status-connected: oklch(var(--brand-l) var(--brand-c) var(--brand-h)); --status-error: oklch(0.704 0.191 22.216); + --series-1: #3987e5; + --series-2: #d95926; + --series-3: #199e70; + --series-4: #c98500; + --series-5: #d55181; + --series-6: #008300; + --series-7: #9085e9; + --routing-apps: oklch(0.72 0.19 350); --routing-domains: oklch(0.7 0.18 300); --routing-ip: oklch(0.75 0.16 45); @@ -993,3 +1010,10 @@ :root[data-backdrop] [data-slot="sheet-content"] { background-color: oklch(var(--ui-bg-l) var(--ui-c) var(--ui-h)); } + +/* The sidebar's wrapper already carries the see-through tint; painting the + inner panel too doubled it inside the wrapper's padding, which showed as a + hard edge down the sidebar's left side. */ +:root[data-backdrop] [data-slot="sidebar-inner"] { + background: transparent; +} diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 5dfa112..30c5cf8 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -804,6 +804,7 @@ function App() { }, [profilesOf] ); + const profileIdsOf = useCallback((source: ConfigSource) => profilesOf(source).map((profile) => profile.id), [profilesOf]); const handleCopySources = useCallback( async (list: ConfigSource[]) => { const links = list.map(linkOf).filter(Boolean); @@ -1004,7 +1005,6 @@ function App() { onMinimize={appWindow.minimize} onMaximize={appWindow.toggleMaximize} platform={platform} - status={connection.state.status} /> setIsModalOpen(true)} /> )} {isMobile ? ( - + ) : null} diff --git a/frontend/src/components/layout/AppSidebar.tsx b/frontend/src/components/layout/AppSidebar.tsx index 7986cca..bb32a2c 100644 --- a/frontend/src/components/layout/AppSidebar.tsx +++ b/frontend/src/components/layout/AppSidebar.tsx @@ -14,7 +14,6 @@ import { import { MacWindowControls } from "@/components/layout/MacWindowControls"; import { MessageKey, useI18n } from "@/lib/i18n"; import { cn } from "@/lib/utils"; -import { ConnectionStatus } from "@/types"; interface AppSidebarProps { activeTab: string; @@ -23,7 +22,6 @@ interface AppSidebarProps { onMinimize: () => void; onMaximize: () => void; platform?: string; - status: ConnectionStatus; } export const TABS = [ @@ -36,19 +34,6 @@ export const TABS = [ { id: "logs", label: "nav.logs", icon: FileText }, ] as const satisfies readonly { id: string; label: MessageKey; icon: unknown }[]; -export const STATUS_DOT: Record = { - idle: "bg-status-idle", - connecting: "bg-status-connecting animate-pulse", - connected: "bg-status-connected", - error: "bg-status-error", -}; - -const STATUS_LABEL: Record = { - idle: "status.idle", - connecting: "status.connecting", - connected: "status.connected", - error: "status.error", -}; function AppSidebar({ activeTab, @@ -57,7 +42,6 @@ function AppSidebar({ onMinimize, onMaximize, platform, - status, }: AppSidebarProps) { const { t, dir } = useI18n(); const isMac = platform === "macos"; @@ -104,16 +88,6 @@ function AppSidebar({ - {/* The tunnel state is visible from every screen, not only the - one screen that happens to be about connecting. */} -
-
- (PRIMARY.map((tab) => tab.id)); export function BottomNav({ activeTab, onTabChange, - status, }: { activeTab: string; onTabChange: (tab: string) => void; - status: ConnectionStatus; }) { const t = useT(); const [more, setMore] = useState(false); @@ -57,9 +54,6 @@ export function BottomNav({