diff options
| author | Dustin Mierau <dustin@mierau.me> | 2023-12-11 23:32:28 -0800 |
|---|---|---|
| committer | Dustin Mierau <dustin@mierau.me> | 2023-12-11 23:32:28 -0800 |
| commit | 18c4b8643df09be4ce52a4b110ea21ac1ad053fc (patch) | |
| tree | 335d4f0a6b430b983b6f00567b91eb1ee6b16b4b /Hotline/Views/TrackerView.swift | |
| parent | 84aaa9ef0a1be6986e38d7e4f58e07d3cb84979e (diff) | |
Move to new Hotline model for data observation and let client exist standalone.
Diffstat (limited to 'Hotline/Views/TrackerView.swift')
| -rw-r--r-- | Hotline/Views/TrackerView.swift | 214 |
1 files changed, 195 insertions, 19 deletions
diff --git a/Hotline/Views/TrackerView.swift b/Hotline/Views/TrackerView.swift index 2d2032e..2fc27c7 100644 --- a/Hotline/Views/TrackerView.swift +++ b/Hotline/Views/TrackerView.swift @@ -1,20 +1,172 @@ import SwiftUI +struct TrackerConnectView: View { + @Environment(Hotline.self) private var model: Hotline + @Environment(\.dismiss) var dismiss + @Environment(\.colorScheme) var colorScheme + + @State private var server: Server? + @State private var address = "" + @State private var login = "" + @State private var password = "" + @State private var connecting = false + + func connectionStatusToProgress(status: HotlineNewClientStatus) -> Double { + switch status { + case .disconnected: + return 0.0 + case .connecting: + return 0.1 + case .connected: + return 0.25 + case .loggingIn: + return 0.5 + case .loggedIn: + return 1.0 + } + } + + + + var body: some View { + VStack(alignment: .leading) { + if !connecting { + TextField("Server Address", text: $address) + .keyboardType(.URL) + .disableAutocorrection(true) + .frame(height: 48) + .textFieldStyle(.plain) + .padding(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16)) + .background { + Color.black.cornerRadius(8).blendMode(.overlay) + } + TextField("Login", text: $login) + .disableAutocorrection(true) + .frame(height: 48) + .textFieldStyle(.plain) + .padding(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16)) + .background { + Color.black.cornerRadius(8).blendMode(.overlay) + } + SecureField("Password", text: $password) + .disableAutocorrection(true) + .textFieldStyle(.plain) + .frame(height: 48) + .padding(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16)) + .background { + Color.black.cornerRadius(8).blendMode(.overlay) + } + } + else { + ProgressView(value: connectionStatusToProgress(status: model.status)) + .frame(minHeight: 10) + .accentColor(colorScheme == .dark ? .white : .black) + } + + Spacer() + + HStack { + Button { + dismiss() + server = nil + model.disconnect() + } label: { + Text("Cancel") + } + .bold() + .padding(EdgeInsets(top: 16, leading: 24, bottom: 16, trailing: 24)) + .frame(maxWidth: .infinity) + .foregroundColor(colorScheme == .dark ? .white : .black) + .background( + colorScheme == .dark ? + LinearGradient(gradient: Gradient(colors: [Color(white: 0.4), Color(white: 0.3)]), startPoint: .top, endPoint: .bottom) + : + LinearGradient(gradient: Gradient(colors: [Color(white: 0.95), Color(white: 0.91)]), startPoint: .top, endPoint: .bottom) + ) + .overlay( + RoundedRectangle(cornerRadius: 10.0).stroke(.black, lineWidth: 3).opacity(colorScheme == .dark ? 0.0 : 0.2) + ) + .cornerRadius(10.0) + Button { + let s = Server(name: address, description: nil, address: address, port: Server.defaultPort, users: 0) + server = s + connecting = true + Task { + let loggedIn = await model.login(server: s, login: login, password: password, username: "bolt", iconID: 128) + if !loggedIn { + connecting = false + } + } + } label: { + Text("Connect") + } + .disabled(connecting) + .bold() + .padding(EdgeInsets(top: 16, leading: 24, bottom: 16, trailing: 24)) + .frame(maxWidth: .infinity) + .foregroundColor(colorScheme == .dark ? .white : .black) + .background( + colorScheme == .dark ? + LinearGradient(gradient: Gradient(colors: [Color(white: 0.4), Color(white: 0.3)]), startPoint: .top, endPoint: .bottom) + : + LinearGradient(gradient: Gradient(colors: [Color(white: 0.95), Color(white: 0.91)]), startPoint: .top, endPoint: .bottom) + ) + .overlay( + RoundedRectangle(cornerRadius: 10.0).stroke(.black, lineWidth: 3).opacity(colorScheme == .dark ? 0.0 : 0.2) + ) + .cornerRadius(10.0) + } + .padding() + } + .padding() + .onChange(of: model.status) { + print("MODEL STATUS CHANGED") + if model.server != nil && server != nil && model.server! == server! { + if model.status == .loggedIn { + dismiss() + } + else { + connecting = (model.status != .disconnected) + } + } + } + .toolbar { + ToolbarItem(placement: .principal) { + Text("Connect to Server") + .font(.headline) + } + } +// .presentationBackground(.regularMaterial, in: Color(uiColor: .systemGroupedBackground)) + .presentationBackground { + Color.clear + .background(Material.regular) + } + .presentationDetents([.height(300), .large]) + .presentationDragIndicator(.visible) + .presentationCornerRadius(20) + // .background(Color(uiColor: .systemGroupedBackground)) + } +} + struct TrackerView: View { // @Environment(\.modelContext) private var modelContext // @Query private var items: [Item] - @Environment(HotlineClient.self) private var hotline @Environment(Hotline.self) private var model: Hotline @Environment(\.colorScheme) var colorScheme -// @State private var tracker = Tracker(address: "hltracker.com", service: trackerService) + // @State private var tracker = Tracker(address: "hltracker.com", service: trackerService) @State private var servers: [Server] = [] @State private var selectedServer: Server? - @State var scrollOffset: CGFloat = CGFloat.zero + @State private var scrollOffset: CGFloat = CGFloat.zero @State private var initialLoadComplete = false + @State private var refreshing = false + @State private var topBarOpacity: Double = 1.0 + @State private var connectVisible = false + @State private var connectDismissed = true + @State private var serverVisible = false func shouldDisplayDescription(server: Server) -> Bool { guard let desc = server.description else { @@ -24,7 +176,7 @@ struct TrackerView: View { return desc.count > 0 && desc != server.name } - func connectionStatusToProgress(status: HotlineClientStatus) -> Double { + func connectionStatusToProgress(status: HotlineNewClientStatus) -> Double { switch status { case .disconnected: return 0.0 @@ -60,7 +212,8 @@ struct TrackerView: View { HStack(alignment: .center) { Spacer() Button { - // hotline.disconnect() + connectVisible = true + connectDismissed = false } label: { Text(Image(systemName: "point.3.connected.trianglepath.dotted")) .symbolRenderingMode(.hierarchical) @@ -68,17 +221,22 @@ struct TrackerView: View { .font(.title2) .padding(.trailing, 16) } + .sheet(isPresented: $connectVisible) { + connectDismissed = true + } content: { + TrackerConnectView() + } } .frame(height: 40.0) } .padding() - .opacity(scrollOffset > 80 ? 0 : 1.0) -// .padding(.top, 5) - .opacity(inverseLerp(lower: -80, upper: 0, v: scrollOffset)) -// .opacity(inverseLerp(lower: 20, upper: 0, v: scrollOffset)) Spacer() } + .opacity(inverseLerp(lower: -50, upper: 0, v: scrollOffset)) + .opacity(scrollOffset > 65 ? 0.0 : 1.0) + .opacity(topBarOpacity) + .zIndex(scrollOffset > 0 ? 1 : 3) ObservableScrollView(scrollOffset: $scrollOffset) { LazyVStack(alignment: .leading) { ForEach(self.servers) { server in @@ -102,14 +260,16 @@ struct TrackerView: View { if server == selectedServer { Spacer(minLength: 16) - if hotline.connectionStatus != .disconnected && hotline.server! == server { - ProgressView(value: connectionStatusToProgress(status: hotline.connectionStatus)) + if model.status != .disconnected && model.server != nil && model.server! == server { + ProgressView(value: connectionStatusToProgress(status: model.status)) .frame(minHeight: 10) .accentColor(colorScheme == .dark ? .white : .black) } else { Button("Connect") { - hotline.connect(to: HotlineServer(address: server.address, port: UInt16(server.port), users: UInt16(server.users), name: server.name, description: server.description)) + Task { + await model.login(server: server, login: "", password: "", username: "bolt", iconID: 128) + } } .bold() .padding(EdgeInsets(top: 16, leading: 24, bottom: 16, trailing: 24)) @@ -119,7 +279,7 @@ struct TrackerView: View { colorScheme == .dark ? LinearGradient(gradient: Gradient(colors: [Color(white: 0.4), Color(white: 0.3)]), startPoint: .top, endPoint: .bottom) : - LinearGradient(gradient: Gradient(colors: [Color(white: 0.95), Color(white: 0.91)]), startPoint: .top, endPoint: .bottom) + LinearGradient(gradient: Gradient(colors: [Color(white: 0.95), Color(white: 0.91)]), startPoint: .top, endPoint: .bottom) ) .overlay( RoundedRectangle(cornerRadius: 10.0).stroke(.black, lineWidth: 3).opacity(colorScheme == .dark ? 0.0 : 0.2) @@ -143,6 +303,7 @@ struct TrackerView: View { } .padding(EdgeInsets(top: 75, leading: 0, bottom: 0, trailing: 0)) } + .zIndex(2) .overlay { if !initialLoadComplete { VStack { @@ -153,29 +314,44 @@ struct TrackerView: View { } } .refreshable { - initialLoadComplete = true + DispatchQueue.main.async { + withAnimation(.easeOut(duration: 0.1)) { + topBarOpacity = 0.0 + } + initialLoadComplete = true + } + + model.disconnectTracker() await updateServers() + + DispatchQueue.main.async { + withAnimation(.easeOut(duration: 1.0).delay(0.75)) { + topBarOpacity = 1.0 + } + } } + } - .fullScreenCover(isPresented: Binding(get: { return hotline.connectionStatus == .loggedIn }, set: { _ in }), onDismiss: { - hotline.disconnect() + .fullScreenCover(isPresented: Binding(get: { return (connectDismissed && serverVisible) }, set: { _ in }), onDismiss: { + model.disconnect() }) { ServerView() } + .onChange(of: model.status) { + serverVisible = (model.status == .loggedIn) + } .background(Color(uiColor: UIColor.systemGroupedBackground)) .frame(maxWidth: .infinity) .task { await updateServers() initialLoadComplete = true -// tracker.fetch() } } } #Preview { TrackerView() - .environment(HotlineClient()) - .environment(HotlineState()) + .environment(Hotline(trackerClient: HotlineTrackerClient(), client: HotlineNewClient())) // .modelContainer(for: Item.self, inMemory: true) } |