核心功能: - ✅ Categories/Series双视图管理(category_view.rs + import_markdown.rs) - ✅ FUSE Multi-Volume支持(tree_type参数) - ✅ SSH/SFTP/SCP/rsync协议完整实现(4042行) - ✅ NFS/SMB Module Phase 1-3完成 - ✅ Archive Module Phase 1-4完成(2916行) - ✅ Download Center API完整实现 - ✅ S3兼容API实现(560行) Git配置修正: - ✅ 删除错误origin(gitea.momentry.ddns.net) - ✅ 删除m5max128(指向机器名) - ✅ 设置origin = m5max128gitea.momentry.ddns.net/admin/markbase - ✅ 设置m4minigitea = m4minigitea.momentry.ddns.net/warren/markbase 数据清理: - ✅ 删除38个临时SQLite(保留accusys.sqlite、demo.sqlite) - ✅ 删除.bak、test_*.bin、调试脚本等临时文件 - ✅ 删除临时目录(build/、download files/、raid_test/等) - ✅ 更新.gitignore排除临时文件 架构优化: - 52个文件修改,2434行新增,4739行删除 - Workspace成员整合(16个crate) - 数据库状态:accusys.sqlite保留(主demo测试) 远程同步: - ✅ 准备推送到m5max128gitea(远程Gitea) - ✅ 准备推送到m4minigitea(本地Gitea)
195 lines
8.5 KiB
Swift
195 lines
8.5 KiB
Swift
import Cocoa
|
|
import SystemExtensions
|
|
import OSLog
|
|
|
|
@main
|
|
struct MarkBaseInstallerApp {
|
|
static func main() {
|
|
let app = NSApplication.shared
|
|
let delegate = AppDelegate()
|
|
app.delegate = delegate
|
|
app.run()
|
|
}
|
|
}
|
|
|
|
class AppDelegate: NSObject, NSApplicationDelegate {
|
|
let logger = Logger(subsystem: "com.momentry.markbase.installer", category: "AppDelegate")
|
|
var window: NSWindow!
|
|
var statusLabel: NSTextField!
|
|
var installButton: NSButton!
|
|
var activityIndicator: NSProgressIndicator!
|
|
|
|
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
|
logger.info("MarkBase Installer started")
|
|
createWindow()
|
|
setupUI()
|
|
window.makeKeyAndOrderFront(nil)
|
|
}
|
|
|
|
func createWindow() {
|
|
window = NSWindow(
|
|
contentRect: NSRect(x: 0, y: 0, width: 500, height: 400),
|
|
styleMask: [.titled, .closable, .miniaturizable],
|
|
backing: .buffered,
|
|
defer: false
|
|
)
|
|
window.title = "MarkBase Installer"
|
|
window.center()
|
|
window.isReleasedWhenClosed = false
|
|
}
|
|
|
|
func setupUI() {
|
|
let contentView = window.contentView!
|
|
|
|
// Title
|
|
let titleLabel = NSTextField(labelWithString: "MarkBase System Extension Installer")
|
|
titleLabel.font = NSFont.systemFont(ofSize: 18, weight: .bold)
|
|
titleLabel.alignment = .center
|
|
contentView.addSubview(titleLabel)
|
|
|
|
// Status Label
|
|
statusLabel = NSTextField(wrappingLabelWithString: "Ready to install MarkBaseFS System Extension")
|
|
statusLabel.font = NSFont.systemFont(ofSize: 14)
|
|
statusLabel.alignment = .center
|
|
statusLabel.textColor = NSColor.controlTextColor
|
|
contentView.addSubview(statusLabel)
|
|
|
|
// Install Button
|
|
installButton = NSButton(title: "Install System Extension", target: self, action: #selector(installExtension(_:)))
|
|
installButton.bezelStyle = .rounded
|
|
installButton.font = NSFont.systemFont(ofSize: 13, weight: .medium)
|
|
contentView.addSubview(installButton)
|
|
|
|
// Activity Indicator
|
|
activityIndicator = NSProgressIndicator()
|
|
activityIndicator.style = .spinning
|
|
activityIndicator.controlSize = .small
|
|
activityIndicator.isHidden = true
|
|
contentView.addSubview(activityIndicator)
|
|
|
|
// Instructions
|
|
let instructionsLabel = NSTextField(wrappingLabelWithString: "Instructions:\n1. Click Install button\n2. Approve in System Settings → Privacy & Security → System Extensions\n3. Wait for activation")
|
|
instructionsLabel.font = NSFont.systemFont(ofSize: 12)
|
|
instructionsLabel.alignment = .left
|
|
instructionsLabel.textColor = NSColor.secondaryLabelColor
|
|
contentView.addSubview(instructionsLabel)
|
|
|
|
// Layout
|
|
titleLabel.translatesAutoresizingMaskIntoConstraints = false
|
|
statusLabel.translatesAutoresizingMaskIntoConstraints = false
|
|
installButton.translatesAutoresizingMaskIntoConstraints = false
|
|
activityIndicator.translatesAutoresizingMaskIntoConstraints = false
|
|
instructionsLabel.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
NSLayoutConstraint.activate([
|
|
// Title
|
|
titleLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
|
|
titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 40),
|
|
|
|
// Status Label
|
|
statusLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
|
|
statusLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 30),
|
|
statusLabel.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: 0.8),
|
|
|
|
// Install Button
|
|
installButton.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
|
|
installButton.topAnchor.constraint(equalTo: statusLabel.bottomAnchor, constant: 30),
|
|
installButton.widthAnchor.constraint(equalToConstant: 200),
|
|
installButton.heightAnchor.constraint(equalToConstant: 30),
|
|
|
|
// Activity Indicator
|
|
activityIndicator.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
|
|
activityIndicator.topAnchor.constraint(equalTo: installButton.bottomAnchor, constant: 20),
|
|
|
|
// Instructions
|
|
instructionsLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 30),
|
|
instructionsLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -30),
|
|
instructionsLabel.topAnchor.constraint(equalTo: activityIndicator.bottomAnchor, constant: 30),
|
|
instructionsLabel.bottomAnchor.constraint(lessThanOrEqualTo: contentView.bottomAnchor, constant: -30)
|
|
])
|
|
}
|
|
|
|
@objc func installExtension(_ sender: NSButton) {
|
|
logger.info("Install button clicked")
|
|
|
|
let extensionID = "com.momentry.markbase.fskit"
|
|
logger.info("Requesting activation for extension: \(extensionID)")
|
|
|
|
updateStatus("Requesting installation...")
|
|
installButton.isEnabled = false
|
|
activityIndicator.isHidden = false
|
|
activityIndicator.startAnimation(nil)
|
|
|
|
let request = OSSystemExtensionRequest.activationRequest(
|
|
forExtensionWithIdentifier: extensionID,
|
|
queue: .main
|
|
)
|
|
request.delegate = ExtensionDelegate(
|
|
onSuccess: {
|
|
self.logger.info("Extension activated successfully")
|
|
self.updateStatus("✅ Installation successful!\nSystem Extension is now active.")
|
|
self.activityIndicator.stopAnimation(nil)
|
|
self.activityIndicator.isHidden = true
|
|
self.installButton.isEnabled = true
|
|
},
|
|
onError: { error in
|
|
self.logger.error("Extension activation failed: \(error.localizedDescription)")
|
|
self.updateStatus("❌ Installation failed: \(error.localizedDescription)")
|
|
self.activityIndicator.stopAnimation(nil)
|
|
self.activityIndicator.isHidden = true
|
|
self.installButton.isEnabled = true
|
|
},
|
|
onNeedsApproval: {
|
|
self.logger.info("Extension needs user approval")
|
|
self.updateStatus("⏳ Waiting for approval...\nOpen System Settings → Privacy & Security → System Extensions")
|
|
self.activityIndicator.stopAnimation(nil)
|
|
self.activityIndicator.isHidden = true
|
|
}
|
|
)
|
|
|
|
OSSystemExtensionManager.shared.submitRequest(request)
|
|
}
|
|
|
|
func updateStatus(_ message: String) {
|
|
DispatchQueue.main.async {
|
|
self.statusLabel.stringValue = message
|
|
}
|
|
}
|
|
}
|
|
|
|
class ExtensionDelegate: NSObject, OSSystemExtensionRequestDelegate {
|
|
let onSuccess: () -> Void
|
|
let onError: (Error) -> Void
|
|
let onNeedsApproval: () -> Void
|
|
|
|
init(onSuccess: @escaping () -> Void, onError: @escaping (Error) -> Void, onNeedsApproval: @escaping () -> Void) {
|
|
self.onSuccess = onSuccess
|
|
self.onError = onError
|
|
self.onNeedsApproval = onNeedsApproval
|
|
super.init()
|
|
}
|
|
|
|
func request(_ request: OSSystemExtensionRequest, didFinishWithResult result: OSSystemExtensionRequest.Result) {
|
|
Logger(subsystem: "com.momentry.markbase.installer", category: "ExtensionDelegate")
|
|
.info("Request finished with result: \(String(describing: result))")
|
|
onSuccess()
|
|
}
|
|
|
|
func request(_ request: OSSystemExtensionRequest, didFailWithError error: Error) {
|
|
Logger(subsystem: "com.momentry.markbase.installer", category: "ExtensionDelegate")
|
|
.error("Request failed with error: \(error.localizedDescription)")
|
|
onError(error)
|
|
}
|
|
|
|
func requestNeedsUserApproval(_ request: OSSystemExtensionRequest) {
|
|
Logger(subsystem: "com.momentry.markbase.installer", category: "ExtensionDelegate")
|
|
.info("Request needs user approval")
|
|
onNeedsApproval()
|
|
}
|
|
|
|
func request(_ request: OSSystemExtensionRequest, actionForReplacingExtension existing: OSSystemExtensionProperties, withExtension ext: OSSystemExtensionProperties) -> OSSystemExtensionRequest.ReplacementAction {
|
|
Logger(subsystem: "com.momentry.markbase.installer", category: "ExtensionDelegate")
|
|
.info("Replacing extension \(existing.bundleIdentifier) with \(ext.bundleIdentifier)")
|
|
return .replace
|
|
}
|
|
} |