memos/ios/Memos/ContentView.swift

186 lines
6.7 KiB
Swift

import SwiftUI
import WebKit
struct ContentView: View {
@EnvironmentObject var serverManager: ServerManager
@State private var showSettings = false
var body: some View {
NavigationView {
ZStack {
if serverManager.isRunning, let url = serverManager.serverURL {
WebView(url: URL(string: url)!)
.edgesIgnoringSafeArea(.bottom)
} else if let error = serverManager.error {
VStack(spacing: 20) {
Image(systemName: "exclamationmark.triangle")
.font(.system(size: 60))
.foregroundColor(.red)
Text("Server Error")
.font(.title)
Text(error)
.multilineTextAlignment(.center)
.padding()
Button("Retry") {
serverManager.startServer()
}
.buttonStyle(.borderedProminent)
}
.padding()
} else {
VStack(spacing: 20) {
ProgressView()
.scaleEffect(1.5)
Text("Starting Memos Server...")
.font(.title2)
}
}
}
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Text("Memos")
.font(.headline)
}
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: { showSettings = true }) {
Image(systemName: "gear")
}
}
}
.sheet(isPresented: $showSettings) {
SettingsView()
.environmentObject(serverManager)
}
}
}
}
struct WebView: UIViewRepresentable {
let url: URL
func makeUIView(context: Context) -> WKWebView {
let configuration = WKWebViewConfiguration()
configuration.allowsInlineMediaPlayback = true
let webView = WKWebView(frame: .zero, configuration: configuration)
webView.allowsBackForwardNavigationGestures = true
webView.scrollView.contentInsetAdjustmentBehavior = .never
return webView
}
func updateUIView(_ webView: WKWebView, context: Context) {
let request = URLRequest(url: url)
webView.load(request)
}
}
struct SettingsView: View {
@EnvironmentObject var serverManager: ServerManager
@Environment(\.dismiss) var dismiss
var body: some View {
NavigationView {
Form {
Section {
HStack {
Text("Server Status")
Spacer()
Circle()
.fill(serverManager.isRunning ? Color.green : Color.red)
.frame(width: 10, height: 10)
Text(serverManager.isRunning ? "Running" : "Stopped")
.foregroundColor(serverManager.isRunning ? .green : .red)
}
if serverManager.isRunning, let url = serverManager.serverURL {
VStack(alignment: .leading) {
Text("Local URL")
.font(.caption)
.foregroundColor(.secondary)
Text(url)
.font(.footnote)
.textSelection(.enabled)
}
}
} header: {
Text("Server")
}
Section {
Toggle("Allow Network Access", isOn: $serverManager.allowNetworkAccess)
if serverManager.allowNetworkAccess {
if let ipAddress = serverManager.getLocalIPAddress() {
VStack(alignment: .leading) {
Text("Network Address")
.font(.caption)
.foregroundColor(.secondary)
Text("http://\(ipAddress):\(5230)")
.font(.footnote)
.textSelection(.enabled)
}
Text("Other devices on your network can access Memos at the address above.")
.font(.caption)
.foregroundColor(.secondary)
}
} else {
Text("Server is only accessible from this device.")
.font(.caption)
.foregroundColor(.secondary)
}
} header: {
Text("Network")
} footer: {
Text("Enable network access to allow other devices on your local network to connect to your Memos instance.")
}
Section {
Button("Restart Server") {
serverManager.stopServer()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
serverManager.startServer()
}
}
Button("Stop Server", role: .destructive) {
serverManager.stopServer()
dismiss()
}
.disabled(!serverManager.isRunning)
} header: {
Text("Actions")
}
Section {
VStack(alignment: .leading, spacing: 4) {
Text("Port: 5230")
Text("Database: SQLite")
Text("Mode: Production")
}
.font(.footnote)
.foregroundColor(.secondary)
} header: {
Text("Configuration")
}
}
.navigationTitle("Settings")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Done") {
dismiss()
}
}
}
}
}
}
#Preview {
ContentView()
.environmentObject(ServerManager.shared)
}