Skip to content
Open
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
5 changes: 3 additions & 2 deletions SwiftCraftLauncher.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
90CA960A2E5C438F00E705DB /* Swift Craft Launcher.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Swift Craft Launcher.app"; sourceTree = BUILT_PRODUCTS_DIR; };
366249962E5F37A2005B440E /* Swift Craft Launcher.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Swift Craft Launcher.app"; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */

/* Begin PBXFileSystemSynchronizedRootGroup section */
Expand Down Expand Up @@ -44,6 +44,7 @@
isa = PBXGroup;
children = (
9023D8332E3139B5005A53F1 /* SwiftCraftLauncher */,
366249962E5F37A2005B440E /* Swift Craft Launcher.app */,
);
sourceTree = "<group>";
};
Expand Down Expand Up @@ -73,7 +74,7 @@
90E123456789ABCD0002 /* Sparkle */,
);
productName = SwiftCraftLauncher;
productReference = 90CA960A2E5C438F00E705DB /* Swift Craft Launcher.app */;
productReference = 366249962E5F37A2005B440E /* Swift Craft Launcher.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
Expand Down
2 changes: 1 addition & 1 deletion SwiftCraftLauncher/Common/Managers/DownloadManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ class DownloadManager {

// 下载文件到临时位置
do {
let (tempFileURL, response) = try await URLSession.shared.download(from: url)
let (tempFileURL, response) = try await NetworkManager.shared.download(from: url)
defer { try? fileManager.removeItem(at: tempFileURL) }

guard let httpResponse = response as? HTTPURLResponse else {
Expand Down
116 changes: 116 additions & 0 deletions SwiftCraftLauncher/Common/Managers/NetworkManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import Foundation

class NetworkManager {
static let shared = NetworkManager()

private let proxySettings = ProxySettingsManager.shared
private var cachedSession: URLSession?
private var lastProxyConfiguration: ProxyConfiguration?

private init() {
setupProxyChangeObserver()
}

deinit {
cachedSession?.invalidateAndCancel()
}

/// 设置代理配置变化监听
private func setupProxyChangeObserver() {
// 监听代理设置变化
NotificationCenter.default.addObserver(
forName: NSNotification.Name("ProxyConfigurationChanged"),
object: nil,
queue: .main
) { [weak self] _ in
self?.invalidateSession()
}
}

/// 清理缓存的session
private func invalidateSession() {
cachedSession?.invalidateAndCancel()
cachedSession = nil
lastProxyConfiguration = nil
}

/// 获取配置了代理的URLSession
var urlSession: URLSession {
let currentConfig = proxySettings.configuration

// 检查是否需要重新创建session
if let cached = cachedSession,
let lastConfig = lastProxyConfiguration,
lastConfig.isEnabled == currentConfig.isEnabled &&
lastConfig.proxyType == currentConfig.proxyType &&
lastConfig.host == currentConfig.host &&
lastConfig.port == currentConfig.port &&
lastConfig.username == currentConfig.username &&
lastConfig.password == currentConfig.password {
return cached
}

// 清理旧session
invalidateSession()

// 创建新的configuration
let configuration = URLSessionConfiguration.default.copy() as! URLSessionConfiguration

if proxySettings.isProxyEnabled && proxySettings.configuration.isValid {
let config = proxySettings.configuration

var proxyDict: [String: Any] = [:]

if config.proxyType == .http {
proxyDict[kCFNetworkProxiesHTTPEnable as String] = true
proxyDict[kCFNetworkProxiesHTTPProxy as String] = config.host
proxyDict[kCFNetworkProxiesHTTPPort as String] = config.port
proxyDict[kCFNetworkProxiesHTTPSEnable as String] = true
proxyDict[kCFNetworkProxiesHTTPSProxy as String] = config.host
proxyDict[kCFNetworkProxiesHTTPSPort as String] = config.port

// HTTP 认证
if config.hasAuthentication {
proxyDict["HTTPProxyUsername"] = config.username
proxyDict["HTTPProxyPassword"] = config.password
proxyDict["HTTPSProxyUsername"] = config.username
proxyDict["HTTPSProxyPassword"] = config.password
}
} else if config.proxyType == .socks5 {
proxyDict[kCFNetworkProxiesSOCKSEnable as String] = true
proxyDict[kCFNetworkProxiesSOCKSProxy as String] = config.host
proxyDict[kCFNetworkProxiesSOCKSPort as String] = config.port

// SOCKS5 认证
if config.hasAuthentication {
proxyDict["SOCKSUsername"] = config.username
proxyDict["SOCKSPassword"] = config.password
}
}

configuration.connectionProxyDictionary = proxyDict
}

// 创建并缓存session
let session = URLSession(configuration: configuration)
cachedSession = session
lastProxyConfiguration = currentConfig

return session
}

/// 使用代理设置执行网络请求
func data(from url: URL) async throws -> (Data, URLResponse) {
return try await urlSession.data(from: url)
}

/// 使用代理设置下载文件
func download(from url: URL) async throws -> (URL, URLResponse) {
return try await urlSession.download(from: url)
}

/// 使用代理设置执行请求
func data(for request: URLRequest) async throws -> (Data, URLResponse) {
return try await urlSession.data(for: request)
}
}
Loading