import SwiftUI struct MenuView: View { @Bindable var store: MacTetherStore @State private var draft = "" var body: some View { VStack(spacing: 0) { header Divider() feedList Divider() composer } .padding(8) .task { store.connectIfSaved() } } private var header: some View { VStack(alignment: .leading, spacing: 6) { HStack { Circle() .fill(store.connected ? Color.green : Color.secondary) .frame(width: 8, height: 8) Text(store.connected ? "connected · \(store.room)" : "disconnected") .font(.caption).foregroundStyle(.secondary) Spacer() Button(store.connected ? "Disconnect" : "Connect") { store.connected ? store.disconnect() : store.connect() }.font(.caption) } if !store.connected { TextField("http://tether.lan:8765", text: $store.serverURL) .textFieldStyle(.roundedBorder).font(.caption) Button("Connect") { store.connect() } .buttonStyle(.borderedProminent).controlSize(.small) .frame(maxWidth: .infinity) } if store.hasAttemptedConnect, let err = store.lastError { Text(err).font(.caption2).foregroundStyle(.red) } } .padding(.bottom, 6) } private var feedList: some View { ScrollView { LazyVStack(alignment: .leading, spacing: 4) { if store.feed.isEmpty { Text("No messages yet — clipboard changes auto-send when connected.") .font(.caption).foregroundStyle(.secondary) .frame(maxWidth: .infinity, alignment: .center) .padding(.top, 20) } else { ForEach(store.feed) { msg in feedRow(msg) } } } .padding(.vertical, 6) } .frame(minHeight: 120, maxHeight: 240) } private func feedRow(_ item: FeedItem) -> some View { HStack(alignment: .top, spacing: 6) { VStack(alignment: .leading, spacing: 2) { Text(item.text) .font(.caption).lineLimit(3) HStack { Text(item.source).font(.caption2).foregroundStyle(.secondary) Spacer() Text(item.date, style: .time).font(.caption2).foregroundStyle(.secondary) } } Button { store.copyToPasteboard(item) } label: { Image(systemName: "doc.on.doc").font(.caption2) } .buttonStyle(.plain).foregroundStyle(.secondary) } .padding(6) .background(Color.primary.opacity(0.04), in: RoundedRectangle(cornerRadius: 6)) } private var composer: some View { HStack(spacing: 6) { TextField("Send text…", text: $draft) .textFieldStyle(.roundedBorder).font(.caption) .onSubmit { if !draft.isEmpty { store.send(draft); draft = "" } } Button { store.send(draft); draft = "" } label: { Image(systemName: "paperplane.fill") } .disabled(!store.connected || draft.isEmpty) .buttonStyle(.borderedProminent).controlSize(.small) } .padding(.top, 6) } }