aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDustin Mierau <dustin@mierau.me>2023-12-05 15:57:27 -0800
committerDustin Mierau <dustin@mierau.me>2023-12-05 15:57:27 -0800
commitb99219f16792be4a06a89f1f32a59f0bf97bba68 (patch)
tree4503d6f8b8c980c073c0e899da014bbffc4f7e94
parentb1a176ba3da2c7cf815084f0f8109008fe763809 (diff)
Experimenting with files.
-rw-r--r--Hotline.xcodeproj/project.pbxproj4
-rw-r--r--Hotline/Hotline/HotlineClient.swift11
-rw-r--r--Hotline/Hotline/HotlineProtocol.swift63
-rw-r--r--Hotline/Hotline/HotlineTrackerClient.swift8
-rw-r--r--Hotline/Views/FileListView.swift22
-rw-r--r--Hotline/Views/FilesView.swift11
-rw-r--r--Hotline/Views/HotlineView.swift7
-rw-r--r--Hotline/Views/ServerView.swift155
-rw-r--r--Hotline/Views/TrackerServerView.swift100
-rw-r--r--Hotline/Views/TrackerView.swift86
10 files changed, 336 insertions, 131 deletions
diff --git a/Hotline.xcodeproj/project.pbxproj b/Hotline.xcodeproj/project.pbxproj
index 93931f6..f6aa976 100644
--- a/Hotline.xcodeproj/project.pbxproj
+++ b/Hotline.xcodeproj/project.pbxproj
@@ -11,6 +11,7 @@
DA0D698D2B1E7CF700C71DF5 /* UserListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA0D698C2B1E7CF700C71DF5 /* UserListView.swift */; };
DA0D698F2B1E841600C71DF5 /* MessageBoardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA0D698E2B1E841600C71DF5 /* MessageBoardView.swift */; };
DA0D69912B1E894800C71DF5 /* FilesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA0D69902B1E894800C71DF5 /* FilesView.swift */; };
+ DA161B6C2B1FA520000918F3 /* FileListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA161B6B2B1FA520000918F3 /* FileListView.swift */; };
DA43205C2B1D003B00FC8843 /* HotlineClientModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA43205B2B1D003B00FC8843 /* HotlineClientModel.swift */; };
DA43205E2B1D615600FC8843 /* ServerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA43205D2B1D615600FC8843 /* ServerView.swift */; };
DA4F2BF62B1668A700D8ADDC /* HotlineClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA4F2BF52B1668A700D8ADDC /* HotlineClient.swift */; };
@@ -32,6 +33,7 @@
DA0D698C2B1E7CF700C71DF5 /* UserListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserListView.swift; sourceTree = "<group>"; };
DA0D698E2B1E841600C71DF5 /* MessageBoardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageBoardView.swift; sourceTree = "<group>"; };
DA0D69902B1E894800C71DF5 /* FilesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilesView.swift; sourceTree = "<group>"; };
+ DA161B6B2B1FA520000918F3 /* FileListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileListView.swift; sourceTree = "<group>"; };
DA43205B2B1D003B00FC8843 /* HotlineClientModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HotlineClientModel.swift; sourceTree = "<group>"; };
DA43205D2B1D615600FC8843 /* ServerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerView.swift; sourceTree = "<group>"; };
DA4F2BF52B1668A700D8ADDC /* HotlineClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HotlineClient.swift; sourceTree = "<group>"; };
@@ -71,6 +73,7 @@
DA4F2C002B1A558E00D8ADDC /* ChatView.swift */,
DA0D698C2B1E7CF700C71DF5 /* UserListView.swift */,
DA0D69902B1E894800C71DF5 /* FilesView.swift */,
+ DA161B6B2B1FA520000918F3 /* FileListView.swift */,
DA4F2BFC2B1A52EF00D8ADDC /* TrackerServerView.swift */,
DA9CAFBC2B126D5700CDA197 /* TrackerView.swift */,
);
@@ -203,6 +206,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ DA161B6C2B1FA520000918F3 /* FileListView.swift in Sources */,
DA43205C2B1D003B00FC8843 /* HotlineClientModel.swift in Sources */,
DA4F2BFB2B1A518500D8ADDC /* AgreementView.swift in Sources */,
DA43205E2B1D615600FC8843 /* ServerView.swift in Sources */,
diff --git a/Hotline/Hotline/HotlineClient.swift b/Hotline/Hotline/HotlineClient.swift
index de01ae9..d2e3954 100644
--- a/Hotline/Hotline/HotlineClient.swift
+++ b/Hotline/Hotline/HotlineClient.swift
@@ -48,6 +48,7 @@ class HotlineClient {
var userList: [HotlineUser] = []
var chatMessages: [HotlineChat] = []
var messageBoard: String = ""
+ var fileList: [HotlineFile] = []
var userName: String = "bolt"
var userIconID: UInt16 = 128
@@ -406,6 +407,16 @@ class HotlineClient {
self.messageBoard = text
}
}
+ case .getFileNameList:
+ var files: [HotlineFile] = []
+ for fi in transaction.getFieldList(type: .fileNameWithInfo) {
+ let file = fi.getFile()
+// print("GOT FILE: \(file.name) \(file.creator) \(file.type) \(file.fileSize)")
+ files.append(file)
+ }
+ DispatchQueue.main.async {
+ self.fileList = files
+ }
default:
break
}
diff --git a/Hotline/Hotline/HotlineProtocol.swift b/Hotline/Hotline/HotlineProtocol.swift
index 20168b0..3eb4a7d 100644
--- a/Hotline/Hotline/HotlineProtocol.swift
+++ b/Hotline/Hotline/HotlineProtocol.swift
@@ -17,6 +17,65 @@ struct HotlineServer: Identifiable, Hashable {
}
}
+extension UInt32 {
+ func decodeFromUInt32() -> String {
+ let bytes = [
+ UInt8((self >> 24) & 0xFF),
+ UInt8((self >> 16) & 0xFF),
+ UInt8((self >> 8) & 0xFF),
+ UInt8(self & 0xFF)
+ ]
+ return String(bytes: bytes, encoding: .utf8) ?? ""
+ }
+}
+
+struct HotlineFile: Identifiable, Hashable {
+ let id = UUID()
+ let type: String
+ let creator: String
+ let fileSize: UInt32
+ let name: String
+
+ var isExpanded: Bool = false
+ var files: [HotlineFile] = []
+
+ let isFolder: Bool
+
+ static func == (lhs: HotlineFile, rhs: HotlineFile) -> Bool {
+ return lhs.id == rhs.id
+ }
+
+ func hash(into hasher: inout Hasher) {
+ hasher.combine(self.id)
+ }
+
+ init(type: String, creator: String, fileSize: UInt32, fileName: String) {
+ self.type = type
+ self.creator = creator
+ self.fileSize = fileSize
+ self.name = fileName
+
+ self.isFolder = (self.type == "fldr")
+ }
+
+ init(from data: Data) {
+ let typeRaw = data.readUInt32(at: 0)!
+ let creatorRaw = data.readUInt32(at: 4)!
+
+ self.type = typeRaw.decodeFromUInt32()
+ self.creator = creatorRaw.decodeFromUInt32()
+ self.fileSize = data.readUInt32(at: 8)!
+
+ self.isFolder = (self.type == "fldr")
+
+// data.readUInt32(at: 12)! // reserved
+// let nameScript = data.readUInt16(at: 16)! // name script
+
+ let nameLength = data.readUInt16(at: 18)!
+ self.name = data.readString(at: 20, length: Int(nameLength), encoding: .ascii)!
+ }
+}
+
struct HotlineUser: Identifiable, Hashable {
let id: UInt16
let iconID: UInt16
@@ -158,6 +217,10 @@ struct HotlineTransactionField {
func getUser() -> HotlineUser {
return HotlineUser(from: self.data)
}
+
+ func getFile() -> HotlineFile {
+ return HotlineFile(from: self.data)
+ }
}
struct HotlineTransaction {
diff --git a/Hotline/Hotline/HotlineTrackerClient.swift b/Hotline/Hotline/HotlineTrackerClient.swift
index fd4e97b..cff3888 100644
--- a/Hotline/Hotline/HotlineTrackerClient.swift
+++ b/Hotline/Hotline/HotlineTrackerClient.swift
@@ -45,9 +45,9 @@ class HotlineTrackerClient {
self.serverPort = NWEndpoint.Port(rawValue: tracker.port)!
}
- func fetch() {
+ func fetch(_ callback: (() -> Void)? = nil) {
self.reset()
- self.connect()
+ self.connect(callback)
}
private func reset() {
@@ -55,7 +55,7 @@ class HotlineTrackerClient {
self.serverCount = 0
}
- private func connect() {
+ private func connect(_ callback: (() -> Void)? = nil) {
self.connection = NWConnection(host: self.serverAddress, port: self.serverPort, using: .tcp)
self.connection?.stateUpdateHandler = { [weak self] (newState: NWConnection.State) in
switch newState {
@@ -69,11 +69,13 @@ class HotlineTrackerClient {
print("CONNECTION CANCELLED")
DispatchQueue.main.async {
self?.connectionStatus = .disconnected
+ callback?()
}
case .failed(let err):
print("CONNECTION ERROR \(err)")
DispatchQueue.main.async {
self?.connectionStatus = .disconnected
+ callback?()
}
default:
print("CONNECTION OTHER THING")
diff --git a/Hotline/Views/FileListView.swift b/Hotline/Views/FileListView.swift
new file mode 100644
index 0000000..852fce4
--- /dev/null
+++ b/Hotline/Views/FileListView.swift
@@ -0,0 +1,22 @@
+import SwiftUI
+
+struct FileListView: View {
+ var item: HotlineFile
+
+ var body: some View {
+ List {
+ ForEach(item.files) { f in
+ if f.isFolder {
+ DisclosureGroup(f.name, isExpanded: false)
+ }
+ else {
+ Text("HELLO")
+ }
+ }
+ }
+ }
+}
+
+#Preview {
+ FileListView(item: HotlineFile(type: "fldr", creator: "", fileSize: 0, fileName: "Folder"))
+}
diff --git a/Hotline/Views/FilesView.swift b/Hotline/Views/FilesView.swift
index 0e1bb91..d910af2 100644
--- a/Hotline/Views/FilesView.swift
+++ b/Hotline/Views/FilesView.swift
@@ -6,15 +6,8 @@ struct FilesView: View {
@State private var fetched = false
var body: some View {
- ScrollView {
- VStack(spacing: 0) {
- List(hotline.userList) { u in
- HStack(alignment: .firstTextBaseline) {
- Text(u.name).bold().foregroundStyle(u.isAdmin ? Color.red : Color.black)
- }
- }
- .padding()
- }
+ List(hotline.fileList) {
+ FileListView(item: $0)
}
.task {
if !fetched {
diff --git a/Hotline/Views/HotlineView.swift b/Hotline/Views/HotlineView.swift
index fe67f79..713691f 100644
--- a/Hotline/Views/HotlineView.swift
+++ b/Hotline/Views/HotlineView.swift
@@ -5,20 +5,15 @@ struct HotlineView: View {
@Environment(HotlineClient.self) private var hotline
@Environment(HotlineTrackerClient.self) private var tracker
- @State private var isTrackerVisible = true
-
var body: some View {
@Bindable var config = appState
NavigationStack {
- ServerView()
+ TrackerView()
}
.sheet(isPresented: $config.agreementPresented) {
AgreementView(text: hotline.agreement!)
}
- .sheet(isPresented: $config.trackerPresented) {
- TrackerView()
- }
}
}
diff --git a/Hotline/Views/ServerView.swift b/Hotline/Views/ServerView.swift
index 0dafbce..98fd515 100644
--- a/Hotline/Views/ServerView.swift
+++ b/Hotline/Views/ServerView.swift
@@ -4,70 +4,123 @@ struct ServerView: View {
@Environment(HotlineState.self) private var appState
@Environment(HotlineClient.self) private var hotline
@Environment(HotlineTrackerClient.self) private var tracker
-
+
+ let server: HotlineServer
+
+ func connectionStatusTitle(status: HotlineClientStatus) -> String {
+ switch(status) {
+ case .disconnected:
+ return "Disconnected"
+ case .connecting:
+ return "Connecting"
+ case .connected:
+ return "Connected"
+ case .loggingIn:
+ return "Logging In"
+ case .loggedIn:
+ return "Logged In"
+ }
+ }
+
+ func connectionProgress(status: HotlineClientStatus) -> Double {
+ return Double(status.rawValue) / Double(HotlineClientStatus.loggedIn.rawValue)
+ }
+
var body: some View {
@Bindable var config = appState
- TabView {
- NavigationView {
- ChatView()
- .navigationTitle(hotline.server?.name ?? "Hotline")
- .navigationBarTitleDisplayMode(.inline)
- .navigationBarItems(
- leading: Button(action: {
- appState.presentTracker()
- }) {
- Image(systemName: "globe.americas.fill") // Hamburger icon or similar
- .imageScale(.large)
+ NavigationStack {
+ if hotline.connectionStatus != .loggedIn {
+ VStack {
+ Spacer()
+ VStack(alignment: .center) {
+ Text("🌎").font(.largeTitle)
+ Text(server.name!).font(.title3).fontWeight(.medium)
+ Text(server.description!).opacity(0.6).font(.title3)
+ Text(server.address).opacity(0.6).font(.title3)
+ }
+ Spacer()
+ HStack(alignment: .center) {
+ if hotline.connectionStatus == .disconnected {
+ ProgressView(connectionStatusTitle(status: hotline.connectionStatus), value: connectionProgress(status: hotline.connectionStatus))
+ Button("Connect") {
+ hotline.connect(to: server)
+ // config.dismissTracker()
+ }
+ .bold()
+ .padding(EdgeInsets(top: 16, leading: 24, bottom: 16, trailing: 24))
+ .frame(maxWidth: .infinity)
+ .foregroundColor(.black)
+ .background(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(0.4)
+ )
+ .cornerRadius(10.0)
}
- )
-// .toolbarBackground(.visible, for: .navigationBar)
-// .toolbarBackground(.red, for: .navigationBar)
- }
- .tabItem {
- Image(systemName: "message")
- }
-
- NavigationView {
- UserListView()
- .navigationTitle("User List")
- .navigationBarTitleDisplayMode(.inline)
- }
- .tabItem {
- Image(systemName: "person.fill")
- }
-
- Text("News")
- .tabItem {
- Image(systemName: "newspaper")
+ else {
+ ProgressView("", value: Double(hotline.connectionStatus.rawValue / HotlineClientStatus.loggedIn.rawValue))
+ }
+ }
}
-
- NavigationView {
- MessageBoardView()
- .navigationTitle("Message Board")
- .navigationBarTitleDisplayMode(.inline)
+ .padding()
}
- .tabItem {
- Image(systemName: "pin")
+ else {
+ TabView {
+ ChatView()
+ .navigationTitle(hotline.server?.name ?? "Hotline")
+ .navigationBarTitleDisplayMode(.inline)
+ .navigationBarItems(
+ leading: Button(action: {
+ appState.presentTracker()
+ }) {
+ Image(systemName: "globe.americas.fill") // Hamburger icon or similar
+ .imageScale(.large)
+ }
+ )
+ // .toolbarBackground(.visible, for: .navigationBar)
+ // .toolbarBackground(.red, for: .navigationBar)
+ .tabItem {
+ Image(systemName: "message")
+ }
+
+ UserListView()
+ .navigationTitle("User List")
+ .navigationBarTitleDisplayMode(.inline)
+ .tabItem {
+ Image(systemName: "person.fill")
+ }
+
+ Text("News")
+ .tabItem {
+ Image(systemName: "newspaper")
+ }
+
+ MessageBoardView()
+ .navigationTitle("Message Board")
+ .navigationBarTitleDisplayMode(.inline)
+ .tabItem {
+ Image(systemName: "pin")
+ }
+
+ FilesView()
+ .navigationTitle("Files")
+ .navigationBarTitleDisplayMode(.inline)
+ .tabItem {
+ Image(systemName: "folder")
+ }
+ }
}
- NavigationView {
- FilesView()
- .navigationTitle("Files")
- .navigationBarTitleDisplayMode(.inline)
- }
- .tabItem {
- Image(systemName: "folder")
- }
+ // .sheet(isPresented: Binding(get: { hotline.connectionStatus != .loggedIn }, set: { _ in })) {
+ // TrackerView()
+ // }
}
-// .sheet(isPresented: Binding(get: { hotline.connectionStatus != .loggedIn }, set: { _ in })) {
-// TrackerView()
-// }
}
}
#Preview {
- ServerView()
+ ServerView(server: HotlineServer(address: "192.168.1.1", port: 5050, users: 5, name: "Ye Olde Server", description: "This is a server"))
.environment(HotlineClient())
.environment(HotlineTrackerClient(tracker: HotlineTracker("hltracker.com")))
+ .environment(HotlineState())
}
diff --git a/Hotline/Views/TrackerServerView.swift b/Hotline/Views/TrackerServerView.swift
index 2c0f3e3..5288496 100644
--- a/Hotline/Views/TrackerServerView.swift
+++ b/Hotline/Views/TrackerServerView.swift
@@ -3,50 +3,92 @@ import SwiftUI
struct TrackerServerView: View {
@Environment(HotlineState.self) private var appState
@Environment(HotlineClient.self) private var hotline
- @Environment(\.dismiss) private var dismiss
let server: HotlineServer
+ @State private var expanded = false
+
+ func shouldDisplayDescription(server: HotlineServer) -> Bool {
+ guard let name = server.name, let desc = server.description else {
+ return false
+ }
+
+ return desc.count > 0 && desc != name && !desc.contains(/^-+/)
+ }
+
var body: some View {
@Bindable var config = appState
VStack(alignment: .leading) {
- HStack {
- Text("🌎").dynamicTypeSize(.xxxLarge)
- Text(server.name!).bold().dynamicTypeSize(.xxxLarge)
- }
- .padding(EdgeInsets(top: 0, leading: 0, bottom: 8.0, trailing: 0))
-
- Text(server.description!).opacity(0.6).dynamicTypeSize(.xLarge).padding(EdgeInsets(top: 0, leading: 0, bottom: 8.0, trailing: 0)).textSelection(.enabled)
- Text(server.address).opacity(0.3).dynamicTypeSize(.medium).textSelection(.enabled)
-
- Spacer()
-
- HStack(alignment: .center) {
- Button("Connect") {
- hotline.connect(to: server)
- config.dismissTracker()
-// dismiss()
+ HStack(alignment: .firstTextBaseline) {
+ Text("🌎").font(.title3)
+ VStack(alignment: .leading) {
+ Text(server.name!).font(.title3).fontWeight(.medium)
+ if shouldDisplayDescription(server: server) {
+ Text(server.description!).opacity(0.6).font(.title3)
+ }
}
- .bold()
- .padding(EdgeInsets(top: 16, leading: 24, bottom: 16, trailing: 24))
- .frame(maxWidth: .infinity)
- .foregroundColor(.black)
- .background(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(0.4)
- )
- .cornerRadius(10.0)
}
+ .padding()
+ .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
+ .listRowSeparator(.hidden)
+ .listRowBackground(Color(white: 0.96))
+
+ // .padding(EdgeInsets(top: 0, leading: 0, bottom: 8.0, trailing: 0))
+// ProgressView(value: 0.5)
+//
+// HStack(alignment: .center) {
+// Button("Connect") {
+// hotline.connect(to: server)
+// config.dismissTracker()
+// // dismiss()
+// }
+// .bold()
+// .padding(EdgeInsets(top: 16, leading: 24, bottom: 16, trailing: 24))
+// .frame(maxWidth: .infinity)
+// .foregroundColor(.black)
+// .background(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(0.4)
+// )
+// .cornerRadius(10.0)
+// }
}
- .padding(EdgeInsets(top: 28.0, leading: 24.0, bottom: 24.0, trailing: 24.0))
+// label: {
+// HStack(alignment: .firstTextBaseline) {
+// Text("🌎").font(.title3)
+// VStack(alignment: .leading) {
+// Text(server.name!).font(.title3).fontWeight(.medium)
+// if shouldDisplayDescription(server: server) {
+// Spacer()
+// Text(server.description!).opacity(0.6).font(.title3)
+// }
+// }
+// }
+// .padding()
+// .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
+// .listRowSeparator(.hidden)
+// .listRowBackground(Color(white: 0.96))
+// }
+ .popover(isPresented: $expanded) {
+ Text("Popover Content")
+ .padding()
+ }
+ .background(Color(white: 0.96))
+ .padding(EdgeInsets(top: 8.0, leading: 24.0, bottom: 8.0, trailing: 24.0))
.presentationDetents([.fraction(0.4)])
- .presentationDragIndicator(.automatic)
+ .presentationDragIndicator(.visible)
+ .onTapGesture {
+ expanded = true
+// withAnimation {
+// expanded.toggle()
+// }
+ }
}
}
#Preview {
TrackerServerView(server: HotlineServer(address: "192.168.1.1", port: 5050, users: 5, name: "Ye Olde Server", description: "This is a server"))
.environment(HotlineClient())
+ .environment(HotlineState())
}
diff --git a/Hotline/Views/TrackerView.swift b/Hotline/Views/TrackerView.swift
index edb2330..83a4ebf 100644
--- a/Hotline/Views/TrackerView.swift
+++ b/Hotline/Views/TrackerView.swift
@@ -11,48 +11,67 @@ struct TrackerView: View {
@State private var selectedServer: HotlineServer?
+ func shouldDisplayDescription(server: HotlineServer) -> Bool {
+ guard let name = server.name, let desc = server.description else {
+ return false
+ }
+
+ return desc.count > 0 && desc != name && !desc.contains(/^-+/)
+ }
+
var body: some View {
@Bindable var config = appState
- NavigationView {
- List(selection: $selectedServer) {
- ForEach(tracker.servers) { server in
- TrackerServerView(server: server)
+ List(selection: $selectedServer) {
+ ForEach(tracker.servers) { server in
+ NavigationLink {
+ ServerView(server: server)
+ } label: {
+ HStack(alignment: .firstTextBaseline) {
+ Text("🌎").font(.title3)
+ VStack(alignment: .leading) {
+ Text(server.name!).font(.title3).fontWeight(.medium)
+ if shouldDisplayDescription(server: server) {
+ Text(server.description!).opacity(0.6).font(.title3)
+ }
+ }
+ }
}
}
- .background(Color(white: 0.96))
- .listStyle(.plain)
- .frame(maxWidth: .infinity)
- .task {
- tracker.fetch()
- }
-// .sheet(item: $selectedServer) { item in
-// TrackerServerView(server: item)
-// }
- .refreshable {
- tracker.fetch()
+ }
+ .background(Color.white)
+ .listStyle(.plain)
+ .listRowSpacing(1)
+ .frame(maxWidth: .infinity)
+ .task {
+ tracker.fetch()
+ }
+ // .sheet(item: $selectedServer) { item in
+ //// Text("HELLO")
+ // TrackerServerView(server: item)
+ // }
+ .refreshable {
+ await withCheckedContinuation { continuation in
+ tracker.fetch() {
+ continuation.resume()
+ }
}
- .navigationTitle("Tracker")
- .navigationBarTitleDisplayMode(.inline)
- .toolbar {
- ToolbarItem(placement: .topBarTrailing) {
- Button {
- config.dismissTracker()
- } label: {
- Image(systemName: "xmark.circle.fill")
- .symbolRenderingMode(.hierarchical)
- .foregroundColor(.gray)
- }
+ }
+ .navigationTitle("Tracker")
+ .navigationBarTitleDisplayMode(.inline)
+ .toolbar {
+ ToolbarItem(placement: .topBarTrailing) {
+ Button {
+ config.dismissTracker()
+ } label: {
+ Image(systemName: "xmark.circle.fill")
+ .symbolRenderingMode(.hierarchical)
+ .foregroundColor(.gray)
}
- // ToolbarItem(placement: .topBarTrailing) {
- // Image(systemName: "camera.fill")
- // }
- // ToolbarItem(placement: .principal) {
- // Text("Username")
- // }
}
}
-// .interactiveDismissDisabled()
+
+ // .interactiveDismissDisabled()
}
}
@@ -60,5 +79,6 @@ struct TrackerView: View {
TrackerView()
.environment(HotlineClient())
.environment(HotlineTrackerClient(tracker: HotlineTracker("hltracker.com")))
+ .environment(HotlineState())
// .modelContainer(for: Item.self, inMemory: true)
}