Skip to content

Macos#21

Merged
lkebin merged 89 commits into
mainfrom
macos
Jul 16, 2026
Merged

Macos#21
lkebin merged 89 commits into
mainfrom
macos

Conversation

@lkebin

@lkebin lkebin commented Jul 16, 2026

Copy link
Copy Markdown
Owner

No description provided.

lkebin and others added 30 commits July 13, 2026 11:53
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
…eRepository

Two fixes:

1. Directory guard in importFile(from:):
   - Added a check using fileExists(atPath:isDirectory:) to reject directory sources
   - Throws FileRepositoryError.notAFile(name) if source is a directory
   - Prevents accidentally copying a directory tree into the flat files/ directory

2. validateName now returns the trimmed name:
   - Changed signature from throws -> Void to throws -> String
   - All callers (exists, importFile, exportFile, renameFile, deleteFile, filePath)
     now use the returned trimmed name for appending paths, ensuring names with
     leading/trailing whitespace don't create files with spaces in their names.
   - renameFile no longer does a separate inline trim; both oldName and newName
     go through validateName.
…te dialogs

Co-Authored-By: Claude <noreply@anthropic.com>
- Moved .fileImporter from emptyView and fileListView to the top-level body Group
- Removed redundant as? String cast in .fileExporter's item parameter

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
- Replace SettingsView body with TabView wrapper (Profiles + Files tabs)
- Extract existing NavigationSplitView into profilesTab computed property
- Add selectedTab state variable
- Add FileManageView.swift and FileRepository.swift to Xcode project target
- Add @available(macOS 14.0, *) annotations to fix build errors
- Fix NSHostingController<SettingsView> reference in MacExtrasConfigurator

Co-Authored-By: Claude <noreply@anthropic.com>
…tion

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
…mport/export

Required by NSOpenPanel (.fileImporter) and NSSavePanel (.fileExporter)
in sandboxed macOS apps.

Co-Authored-By: Claude <noreply@anthropic.com>
.fileImporter provides security-scoped URLs that require
startAccessingSecurityScopedResource() before reading in sandboxed apps.
Also make ensureDir() throw instead of silently failing.

Co-Authored-By: Claude <noreply@anthropic.com>
…ct toolbar

- Profiles tab: hide scroll background for cleaner sidebar look
- Files tab: remove header text, replace ellipsis button with contextMenu
- Files tab: add compact import button at bottom, plain list style

Co-Authored-By: Claude <noreply@anthropic.com>
…using plain list style

Co-Authored-By: Claude <noreply@anthropic.com>
- Use ToolbarItem(placement: .principal) for centered GostX title
- Remove window.title from MacExtrasConfigurator (now handled by SwiftUI toolbar)
- Restore .sidebar list style for native macOS sidebar appearance

Co-Authored-By: Claude <noreply@anthropic.com>
…ore window.title

- Remove scrollContentBackground(.hidden) — caused visual glitches
- Restore window.title in MacExtrasConfigurator
- Use fixed .navigationTitle("GostX") instead of dynamic profile name

Co-Authored-By: Claude <noreply@anthropic.com>
lkebin added 25 commits July 15, 2026 22:20
- LogOptionsView: change @State to @binding for loggingEnabled and logLevel
  so parent SettingsView state flows through to LogContentView
- SettingsView: add logLevel @State, pass bindings to LogOptionsView
- FileListView: restore isAvailable guard with unavailable view when
  App Group container is nil
- LogOptionsView: use LabeledContent + .menu picker (dropdown) instead of radio group
- ProfileListView/FileListView: add 8pt horizontal padding for content margins
- MacExtrasConfigurator: unifiedTitleAndToolbar + transparent titlebar + .unified toolbarStyle for Liquid Glass sidebar-titlebar fusion
Matches NetNewsWire's storyboard configuration. fullSizeContentView makes
the NavigationSplitView content extend into the titlebar area, enabling
the sidebar to fuse with the window titlebar like Liquid Glass.
Combined with fullSizeContentView + titlebarAppearsTransparent + .unified
toolbarStyle, this allows the NavigationSplitView sidebar to extend into
the titlebar area.
Per Apple docs, NavigationSplitView automatically adopts Liquid Glass
on macOS 26. Custom fullSizeContentView/ignoresSafeArea may interfere.
Minimal toolbar delegate provides the toolbar area that NavigationSplitView
sidebar can potentially fuse into on macOS 26.
…bar fusion

Restores fullSizeContentView + titlebarAppearsTransparent + .unified
toolbarStyle alongside NSToolbar and ignoresSafeArea — matching
NetNewsWire's approach with NavigationSplitView.
NSScrollView (YamlTextView) respects safe area insets, leaving a gap
matching the toolbar height. SwiftUI TextEditor (FileContentView) ignores
it automatically. Add ignoresSafeArea(.container, edges: .top) to match.
Now matches Files behavior — no profile is selected by default when
switching to Profiles, showing the placeholder view instead.
Matches the system Preferences pattern: section title, rounded card
container with rows (label left, control right), thin dividers.
…Area top

Matches FileContentView pattern: content then Divider then action buttons.
Toolbar hidden when logging off. Added ignoresSafeArea(.container, .top)
for toolbar-height gap fix.
…back

Timer's scrollTo ran before SwiftUI re-rendered, targeting IDs that didn't
exist yet. onChange(of: lines.count) fires after SwiftUI updates the view,
guaranteeing the target is in the view hierarchy.
…abled

- isFollowing default changed from true to false
- onAppear(loggingEnabled:) checks state before starting poll timer
- LogViewModelTests updated
macOS 26 is Apple Silicon only. Libgost.xcframework only ships arm64.
Archiving was failing because Xcode builds for x86_64+arm64 by default.
…ned runtime

- Removed CODE_SIGN_IDENTITY=Apple Development from Release (let Automatic pick Developer ID)
- ENABLE_HARDENED_RUNTIME = YES for notarization compatibility
Automates: archive → export → DMG → optional notarization
Requires Developer ID Application certificate. Notarization enabled via
APPLE_ID, APPLE_PASSWORD, APPLE_TEAM environment variables.
Changed packet-tunnel-provider → packet-tunnel-provider-systemextension
to match the provisioning profile generated by Automatic Signing.
Copilot AI review requested due to automatic review settings July 16, 2026 03:39
@lkebin
lkebin merged commit 34172e2 into main Jul 16, 2026
1 check passed
@lkebin
lkebin deleted the macos branch July 16, 2026 03:39

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a macOS build + runtime path for GostX alongside the existing Android flow. This introduces a macOS Packet Tunnel Provider extension backed by the Go libgost engine (xcframework via gomobile bind), plus macOS Settings UX for multi-profile YAML editing, file management, and log viewing via an App Group container.

Changes:

  • Add root make macos / make macos-release targets and a libgost macos-xcframework build target to produce/copy Libgost.xcframework.
  • Implement macOS VPN mode via NETunnelProviderManager + NEPacketTunnelProvider, sharing YAML/log settings through an App Group.
  • Add macOS Settings NavigationSplitView UI: profiles (YAML editor), files (App Group files/), logs (options + content), plus unit tests for LogViewModel.

Reviewed changes

Copilot reviewed 43 out of 53 changed files in this pull request and generated 16 comments.

Show a summary per file
File Description
Makefile Adds macOS build and release targets; copies Libgost.xcframework into macos/Frameworks/.
macos/GostXTunnel/PacketTunnelProvider.swift Implements Packet Tunnel startup/shutdown via Libgost + App Group YAML/log settings.
macos/GostXTunnel/Info.plist Declares the packet-tunnel extension principal class and extension point.
macos/GostXTunnel/GostXTunnel.entitlements Adds sandbox/App Group and Network Extension entitlements for the tunnel.
macos/GostXTests/GostXTests.swift Adds unit tests for LogViewModel file loading/clear/copy behavior.
macos/GostX/YamlEditorView.swift Adds a custom NSTextView wrapper with YAML highlighting + undo support.
macos/GostX/VpnManager.swift Adds NETunnelProviderManager lifecycle + start/stop wrapper.
macos/GostX/SettingsView.swift Reworks Settings into a 3-column NavigationSplitView (Profiles/Files/Logs).
macos/GostX/ProfileListView.swift Adds profile CRUD UI bound to ConfigRepository.
macos/GostX/MacExtrasConfigurator.swift Updates status bar menu: profiles submenu + settings window + VPN status observation.
macos/GostX/LogViewModel.swift Adds log polling + copy/clear logic.
macos/GostX/LogOptionsView.swift Adds logging enable toggle + level selection persisted via App Group defaults.
macos/GostX/LogContentView.swift Adds log viewer with auto-scroll follow/pause and clipboard/truncate actions.
macos/GostX/GostX.entitlements Adds App Group + Network Extension entitlements for the main app.
macos/GostX/FileRepository.swift Adds App Group files/ directory CRUD and filename validation.
macos/GostX/FileManageViewModel.swift Adds file list/import/export/rename/delete view model for sandboxed file handling.
macos/GostX/FileListView.swift Adds Files list UI with importer/exporter + rename/delete dialogs.
macos/GostX/FileContentView.swift Adds file content editor + save flow for selected App Group files.
macos/GostX/ConfigRepository.swift Adds multi-profile YAML persistence + active profile sync to App Group YAML.
macos/GostX/Arguments.swift Adds additional constants (keys/filenames) alongside defaultGostYAML.
macos/GostX/AppLogger.swift Adds unified logging bridge that writes app logs to shared gost.log.
macos/GostX/AppGroupConfig.swift Adds App Group YAML + logging preferences (suite defaults) helpers.
macos/GostX/AppDelegate.swift Switches to Libgost and adds VPN/proxy mode start/stop orchestration.
macos/GostX.xcodeproj/xcshareddata/xcschemes/GostX.xcscheme Updates scheme upgrade metadata.
macos/GostX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved Removes SPM resolution for HighlightedTextEditor dependency.
macos/GostX.xcodeproj/project.pbxproj Adds new targets/files/frameworks; embeds tunnel extension; updates build settings.
macos/Configuration/ExportOptions.plist Adds export options for Developer ID distribution.
macos/Configuration/DevelopmentTeam.example.xcconfig Adds example xcconfig for signing Team ID configuration.
libgost/tun.go Makes sing-tun stack type configurable (system vs gvisor) and improves logs.
libgost/tun_test.go Minor formatting change (trailing newline).
libgost/tun_stack_default.go Adds default stack type for non-darwin platforms.
libgost/tun_stack_darwin.go Selects gvisor stack type on darwin due to utun/system-stack behavior.
libgost/tun_darwin.go Adds utun file descriptor discovery on darwin by scanning FDs.
libgost/tun_darwin_test.go Adds darwin-only test for tunnel FD discovery (expects -1 typically).
libgost/Makefile Adds macos-xcframework target and cleans xcframework output.
drawing.svg Updates export DPI metadata.
docs/superpowers/specs/2026-07-14-makefile-macos-target-design.md Adds design spec for Makefile macOS build targets.
docs/superpowers/specs/2026-07-13-macos-tun-design.md Adds macOS TUN/VPN design documentation.
docs/superpowers/specs/2026-07-13-macos-file-manager-design.md Adds macOS bypass-file manager design spec.
docs/superpowers/specs/2025-07-16-macos-settings-navigationsplitview-design.md Adds Settings NavigationSplitView design spec.
docs/superpowers/plans/2026-07-14-makefile-macos-target.md Adds implementation plan for Makefile macOS targets.
docs/superpowers/plans/2026-07-13-macos-tun-implementation.md Adds detailed implementation plan for macOS TUN/VPN support.
docs/superpowers/plans/2026-07-13-macos-file-manager.md Adds implementation plan for macOS bypass-file manager.
.gitignore Ignores macOS build artifacts, Frameworks dir, and xcconfig secrets; adds xcframework ignores.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

private func startVpnMode() {
AppLogger.log(.info, "Starting VPN mode")
// 同步 YAML 到 App Group
let yaml = UserDefaults.standard.string(forKey: defaultsYamlKey) ?? defaultGostYAML

private func startProxyMode() {
AppLogger.log(.info, "Starting proxy mode")
let yaml = UserDefaults.standard.string(forKey: defaultsYamlKey) ?? defaultGostYAML
Comment on lines +83 to +88
AppLogger.log(.info, "Stopping...")
if vpnMode {
Task { @MainActor in VpnManager.shared.stop() }
} else {
LibgostStopGost(nil)
}
Comment on lines +112 to +114
try await VpnManager.shared.start()
DispatchQueue.main.async { self.menu?.toOnState() }
AppLogger.log(.info, "VPN started")
Comment on lines +145 to +146
self.menu?.toOnState()
AppLogger.log(.info, "Proxy started")
Comment on lines +30 to +33
queue.async {
let timestamp = ISO8601DateFormatter().string(from: Date())
let entry = "\(formatTimestamp()) \(line)\n"
if let data = entry.data(using: .utf8) {
Comment thread libgost/Makefile
Comment on lines +50 to +52
# macOS .xcframework via gomobile bind
# Produces Libgost.xcframework with macos-arm64_x86_64 slices.
# Xcode links this into the PacketTunnelProvider Extension target.
Comment on lines +126 to +131
.fileExporter(
isPresented: $showExporter,
item: exportName ?? "",
contentTypes: [.data],
defaultFilename: exportName ?? "file"
) { result in
Comment on lines 4 to +24
// Storage key for the YAML configuration (gost v3 format).
let defaultsArgumentsKey = "gost_yaml_config"

let defaultGostYAML = """
services:
- name: socks5-outbound
addr: :1080
handler:
type: socks5
listener:
type: tcp
"""

// YAML 持久化 key(UserDefaults)
let defaultsYamlKey = "gost_yaml_config"

// VPN 模式 key
let defaultsVpnModeKey = "gost_vpn_mode_enabled"

// App Group 容器目录下 YAML 文件名
let appGroupYamlFileName = "gost.yaml"
@available(macOS 14.0, *)
struct YamlEditorView: View {
let profileId: String
@StateObject private var repo = ConfigRepository.shared
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants