mirror of
https://github.com/StikDebug/StikDebug.git
synced 2026-10-15 20:10:30 +00:00
* Heartbeat rework * remove some debug loggings * stik mini tool poc * Saperate JITEnableContext into extensions and put each feature into their own files. Fix local pairing file is removed after switched to external device by directly loading the remote device's pairing file in place. * custom origin & xmlhttprequest * Fix some memory leak * allow background script access idevice (codes are from the old JSSupport branch) Tests are not carried out but most of the js api should work. Do we need to obfuscate some functions' name? * Fix JITEnableContext singleton initializer race condition * Fix instprox callback --------- Co-authored-by: Stephen B <158498287+StephenDev0@users.noreply.github.com>
109 lines
3.9 KiB
Swift
109 lines
3.9 KiB
Swift
import SwiftUI
|
|
import WebKit
|
|
|
|
struct MiniToolRunnerView: View {
|
|
let tool: MiniToolBundle
|
|
@StateObject private var runtime: MiniToolRuntime
|
|
@State private var showLogs = false
|
|
@State private var initiated = false
|
|
|
|
@AppStorage("appTheme") private var appThemeRaw: String = AppTheme.system.rawValue
|
|
@Environment(\.themeExpansionManager) private var themeExpansion
|
|
|
|
private var backgroundStyle: BackgroundStyle { themeExpansion?.backgroundStyle(for: appThemeRaw) ?? AppTheme.system.backgroundStyle }
|
|
private var preferredScheme: ColorScheme? { themeExpansion?.preferredColorScheme(for: appThemeRaw) }
|
|
|
|
init(tool: MiniToolBundle) {
|
|
self.tool = tool
|
|
_runtime = StateObject(wrappedValue: MiniToolRuntime(tool: tool))
|
|
}
|
|
|
|
var body: some View {
|
|
ZStack {
|
|
ThemedBackground(style: backgroundStyle)
|
|
.ignoresSafeArea()
|
|
|
|
VStack(spacing: 12) {
|
|
MiniToolWebContainer(runtime: runtime)
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
.background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 16, style: .continuous))
|
|
.overlay(
|
|
RoundedRectangle(cornerRadius: 16, style: .continuous)
|
|
.strokeBorder(Color.white.opacity(0.12), lineWidth: 1)
|
|
)
|
|
.clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous))
|
|
|
|
if !runtime.logs.isEmpty && showLogs {
|
|
logList
|
|
}
|
|
}
|
|
.padding(16)
|
|
}
|
|
.navigationTitle(tool.name)
|
|
.navigationBarTitleDisplayMode(.inline)
|
|
.onAppear {
|
|
if !initiated {
|
|
runtime.start()
|
|
initiated = true
|
|
}
|
|
}
|
|
.toolbar {
|
|
ToolbarItemGroup(placement: .navigationBarTrailing) {
|
|
Button {
|
|
showLogs.toggle()
|
|
} label: {
|
|
Label("Toggle Log", systemImage: "bubble.left")
|
|
}
|
|
Button {
|
|
runtime.reload()
|
|
} label: {
|
|
Label("Reload", systemImage: "arrow.clockwise")
|
|
}
|
|
}
|
|
}
|
|
.preferredColorScheme(preferredScheme)
|
|
}
|
|
|
|
private var logList: some View {
|
|
VStack(alignment: .leading, spacing: 8) {
|
|
HStack {
|
|
Label("Messages", systemImage: "bubble.left")
|
|
.font(.subheadline.weight(.semibold))
|
|
Spacer()
|
|
}
|
|
ScrollViewReader { proxy in
|
|
ScrollView {
|
|
LazyVStack(alignment: .leading, spacing: 6) {
|
|
ForEach(Array(runtime.logs.enumerated()), id: \.offset) { index, line in
|
|
Text(line)
|
|
.font(.caption.monospaced())
|
|
.id(index)
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
}
|
|
}
|
|
}
|
|
.onChange(of: runtime.logs.count) { _, newCount in
|
|
guard newCount > 0 else { return }
|
|
withAnimation { proxy.scrollTo(newCount - 1, anchor: .bottom) }
|
|
}
|
|
}
|
|
}
|
|
.padding(12)
|
|
.background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 12, style: .continuous))
|
|
.overlay(
|
|
RoundedRectangle(cornerRadius: 12, style: .continuous)
|
|
.strokeBorder(Color.white.opacity(0.12), lineWidth: 1)
|
|
)
|
|
}
|
|
}
|
|
|
|
private struct MiniToolWebContainer: UIViewRepresentable {
|
|
@ObservedObject var runtime: MiniToolRuntime
|
|
|
|
func makeUIView(context: Context) -> WKWebView {
|
|
runtime.webView!
|
|
}
|
|
|
|
func updateUIView(_ uiView: WKWebView, context: Context) {
|
|
}
|
|
}
|