Init commit

This commit is contained in:
世界
2023-07-15 15:03:45 +08:00
commit f441b89efb
122 changed files with 7355 additions and 0 deletions
@@ -0,0 +1,108 @@
import Foundation
import Libbox
import Library
import SwiftUI
public class LogClient: ObservableObject {
private var maxLines: Int
@Published public var isConnected: Bool
@Published public var logList: [String]
private var commandClient: LibboxCommandClient!
private var connectTask: Task<Void, Error>?
public init(_ maxLines: Int) {
self.maxLines = maxLines
isConnected = false
logList = []
}
deinit {
if let connectTask {
connectTask.cancel()
}
if let commandClient {
try? commandClient.disconnect()
}
}
public func reconnect() {
if isConnected {
return
}
if let connectTask {
connectTask.cancel()
}
connectTask = Task.detached {
await self.connect()
}
}
private func connect() async {
let clientOptions = LibboxCommandClientOptions()
clientOptions.command = LibboxCommandLog
clientOptions.statusInterval = Int64(2 * NSEC_PER_SEC)
let client = LibboxNewCommandClient(FilePath.sharedDirectory.relativePath, logHandler(self), clientOptions)!
do {
for i in 0 ..< 10 {
try await Task.sleep(nanoseconds: UInt64(Double(100 + (i * 50)) * Double(NSEC_PER_MSEC)))
try Task.checkCancellation()
let isConnected: Bool
do {
try client.connect()
isConnected = true
} catch {
isConnected = false
}
try Task.checkCancellation()
if isConnected {
commandClient = client
return
}
}
} catch {
try? client.disconnect()
}
}
private class logHandler: NSObject, LibboxCommandClientHandlerProtocol {
private let logClient: LogClient
init(_ logClient: LogClient) {
self.logClient = logClient
}
@MainActor
func connected() {
logClient.logList.removeAll()
logClient.isConnected = true
}
@MainActor
func disconnected(_ message: String?) {
if let message {
logClient.logList.append("(log client closed) \(message)")
} else {
logClient.logList.append("(log client closed)")
}
try? logClient.commandClient?.disconnect()
logClient.commandClient = nil
logClient.isConnected = false
}
@MainActor
func writeLog(_ message: String?) {
guard let message else {
return
}
if logClient.logList.count > logClient.maxLines {
logClient.logList.removeFirst()
}
logClient.logList.append(message)
}
func writeStatus(_: LibboxStatusMessage?) {}
func writeGroups(_: LibboxOutboundGroupIteratorProtocol?) {}
}
}
@@ -0,0 +1,72 @@
import SwiftUI
public struct LogView: View {
@Environment(\.logClient) private var logClient
public init() {}
public var body: some View {
viewBuilder {
if let logClient = logClient.wrappedValue {
LogView0().environmentObject(logClient)
} else {
Text("Service not started")
}
}
.navigationTitle("Logs")
}
private struct LogView0: View {
@Environment(\.selection) private var selection
@Environment(\.extensionProfile) private var extensionProfile
@EnvironmentObject private var logClient: LogClient
private let logFont = Font.system(.caption2, design: .monospaced)
var body: some View {
viewBuilder {
if logClient.logList.isEmpty {
VStack {
if logClient.isConnected {
Text("Empty logs")
} else {
Text("Service not started").onAppear(perform: connectLog)
}
}.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
} else {
ScrollViewReader { reader in
ScrollView {
VStack(alignment: .leading, spacing: 0) {
ForEach(Array(logClient.logList.enumerated()), id: \.offset) { it in
Text(it.element)
.font(logFont)
Spacer(minLength: 5)
}
.onChange(of: logClient.logList.count) { newCount in
withAnimation {
reader.scrollTo(newCount - 1)
}
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
.padding()
}
.onAppear {
reader.scrollTo(logClient.logList.count - 1)
}
}
}
}
}
private func connectLog() {
guard let profile = extensionProfile.wrappedValue else {
return
}
if profile.status.isConnected, !logClient.isConnected {
logClient.reconnect()
}
}
}
}