diff options
| author | Ruben Beltran del Rio <git@r.bdr.sh> | 2025-02-05 22:27:17 +0100 |
|---|---|---|
| committer | Ruben Beltran del Rio <git@r.bdr.sh> | 2025-02-05 22:27:17 +0100 |
| commit | 45829daa856b376b1ab04d415917110b71b1dec5 (patch) | |
| tree | 8e52daed6897b6f489d455736fe256cb9bd90fef /Hotline/iOS | |
| parent | 5c3ea897d062a47bc8cd6255fb8c36bad2f0733f (diff) | |
Apply formatting
Diffstat (limited to 'Hotline/iOS')
| -rw-r--r-- | Hotline/iOS/ChatView.swift | 28 | ||||
| -rw-r--r-- | Hotline/iOS/FilesView.swift | 53 | ||||
| -rw-r--r-- | Hotline/iOS/MessageBoardView.swift | 8 | ||||
| -rw-r--r-- | Hotline/iOS/NewsView.swift | 74 | ||||
| -rw-r--r-- | Hotline/iOS/ServerView.swift | 12 | ||||
| -rw-r--r-- | Hotline/iOS/TrackerView.swift | 302 | ||||
| -rw-r--r-- | Hotline/iOS/UsersView.swift | 2 |
7 files changed, 244 insertions, 235 deletions
diff --git a/Hotline/iOS/ChatView.swift b/Hotline/iOS/ChatView.swift index dadd5e6..e5105d0 100644 --- a/Hotline/iOS/ChatView.swift +++ b/Hotline/iOS/ChatView.swift @@ -2,20 +2,21 @@ import SwiftUI extension View { func endEditing() { - UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) + UIApplication.shared.sendAction( + #selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) } } struct ChatView: View { @Environment(Hotline.self) private var model: Hotline @Environment(\.colorScheme) var colorScheme - + @State var input: String = "" @State private var scrollPos: Int? @State private var contentHeight: CGFloat = 0 - + @Namespace var bottomID - + var body: some View { NavigationStack { VStack(spacing: 0) { @@ -24,7 +25,7 @@ struct ChatView: View { LazyVStack(alignment: .leading) { ForEach(model.chat) { msg in if msg.type == .agreement { - + VStack(alignment: .center) { if let bannerImage = self.model.bannerImage { Image(uiImage: bannerImage) @@ -33,7 +34,7 @@ struct ChatView: View { .frame(maxWidth: 468.0) .clipShape(RoundedRectangle(cornerRadius: 5)) } - + VStack(alignment: .leading) { HStack { Text(msg.text) @@ -51,8 +52,7 @@ struct ChatView: View { } .frame(maxWidth: .infinity) .padding() - } - else if msg.type == .status { + } else if msg.type == .status { HStack { Spacer() Text(msg.text) @@ -62,13 +62,11 @@ struct ChatView: View { Spacer() } .padding() - } - else { + } else { HStack(alignment: .firstTextBaseline) { if let username = msg.username { Text("**\(username):** \(msg.text)") - } - else { + } else { Text(msg.text) .textSelection(.enabled) } @@ -96,9 +94,9 @@ struct ChatView: View { self.endEditing() } } - + Divider() - + HStack(alignment: .top) { Image(systemName: "chevron.right").opacity(0.4) TextField("", text: $input, axis: .vertical) @@ -144,7 +142,7 @@ struct ChatView: View { } } } - + } } } diff --git a/Hotline/iOS/FilesView.swift b/Hotline/iOS/FilesView.swift index 017a469..70b07c2 100644 --- a/Hotline/iOS/FilesView.swift +++ b/Hotline/iOS/FilesView.swift @@ -3,11 +3,11 @@ import UniformTypeIdentifiers struct FileView: View { @Environment(Hotline.self) private var model: Hotline - + @State var expanded = false - + var file: FileInfo - + var body: some View { if file.isFolder { DisclosureGroup(isExpanded: $expanded) { @@ -17,7 +17,7 @@ struct FileView: View { } } label: { HStack { - HStack(alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/) { + HStack(alignment: /*@START_MENU_TOKEN@*/ .center /*@END_MENU_TOKEN@*/) { Image(systemName: "folder.fill") } .frame(minWidth: 25) @@ -30,20 +30,19 @@ struct FileView: View { if !expanded { return } - + // Some servers don't reply when asking for the contents of an empty folder. if file.isFolder && file.fileSize == 0 { return } - + Task { await model.getFileList(path: file.path) } } - } - else { + } else { HStack { - HStack(alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/) { + HStack(alignment: /*@START_MENU_TOKEN@*/ .center /*@END_MENU_TOKEN@*/) { fileIcon(name: file.name) .renderingMode(.template) } @@ -54,53 +53,49 @@ struct FileView: View { } } } - + static let byteFormatter = ByteCountFormatter() - + private func formattedFileSize(_ fileSize: UInt) -> String { // let bcf = ByteCountFormatter() FileView.byteFormatter.allowedUnits = [.useAll] FileView.byteFormatter.countStyle = .file return FileView.byteFormatter.string(fromByteCount: Int64(fileSize)) } - + private func fileIcon(name: String) -> Image { // func utTypeForFilename(_ filename: String) -> UTType? { let fileExtension = (name as NSString).pathExtension if let fileType = UTType(filenameExtension: fileExtension) { print("\(name) \(fileExtension) = \(fileType)") - + if fileType.isSubtype(of: .movie) { return Image(systemName: "play.rectangle") -// return UIImage(systemName: "play.rectangle")! - } - else if fileType.isSubtype(of: .image) { + // return UIImage(systemName: "play.rectangle")! + } else if fileType.isSubtype(of: .image) { return Image(systemName: "photo") -// return UIImage(systemName: "photo")! - } - else if fileType.isSubtype(of: .archive) { + // return UIImage(systemName: "photo")! + } else if fileType.isSubtype(of: .archive) { return Image(systemName: "doc.zipper") -// return UIImage(systemName: "doc.zipper")! - } - else if fileType.isSubtype(of: .text) { + // return UIImage(systemName: "doc.zipper")! + } else if fileType.isSubtype(of: .text) { return Image(systemName: "doc.text") -// return UIImage(systemName: "doc.text")! - } - else { + // return UIImage(systemName: "doc.text")! + } else { return Image(systemName: "doc") -// return UIImage(systemName: "doc")! + // return UIImage(systemName: "doc")! } } - + return Image(systemName: "doc") } } struct FilesView: View { @Environment(Hotline.self) private var model: Hotline - + @State var initialLoadComplete = false - + var body: some View { NavigationStack { List(model.files) { file in diff --git a/Hotline/iOS/MessageBoardView.swift b/Hotline/iOS/MessageBoardView.swift index 0d3968f..56fd4cc 100644 --- a/Hotline/iOS/MessageBoardView.swift +++ b/Hotline/iOS/MessageBoardView.swift @@ -2,10 +2,10 @@ import SwiftUI struct MessageBoardView: View { @Environment(Hotline.self) private var model: Hotline - + @State private var initialLoadComplete = false @State private var fetched = false - + var body: some View { NavigationStack { ScrollView { @@ -57,14 +57,14 @@ struct MessageBoardView: View { } ToolbarItem(placement: .navigationBarTrailing) { Button { - + } label: { Image(systemName: "square.and.pencil") } } } } - + } } diff --git a/Hotline/iOS/NewsView.swift b/Hotline/iOS/NewsView.swift index 460dcd3..72dd034 100644 --- a/Hotline/iOS/NewsView.swift +++ b/Hotline/iOS/NewsView.swift @@ -4,16 +4,16 @@ import UniformTypeIdentifiers struct NewsItemView: View { @Environment(Hotline.self) private var model: Hotline @Environment(NewsItemSelection.self) private var selectedArticle: NewsItemSelection - + let news: NewsInfo - + static var dateFormatter: DateFormatter = { var formatter = DateFormatter() formatter.dateFormat = "MM/dd/yy, h:mm a" formatter.timeZone = .gmt return formatter }() - + static var relativeDateFormatter: RelativeDateTimeFormatter = { var formatter = RelativeDateTimeFormatter() formatter.unitsStyle = .abbreviated @@ -21,9 +21,9 @@ struct NewsItemView: View { formatter.formattingContext = .listItem return formatter }() - + @State var expanded = false - + var body: some View { if news.count > 0 { DisclosureGroup(isExpanded: $expanded) { @@ -49,13 +49,12 @@ struct NewsItemView: View { if !expanded { return } - + Task { await model.getNewsList(at: news.path) } } - } - else { + } else { HStack(alignment: .firstTextBaseline) { Text(Image(systemName: "quote.opening")) Text(news.name) @@ -66,13 +65,12 @@ struct NewsItemView: View { Text("\(news.count)") .lineLimit(1) .foregroundStyle(.secondary) - } - else if let postAuthor = news.articleUsername { -// Text("\(NewsItemView.relativeDateFormatter.localizedString(for: postDate, relativeTo: Date.now))") + } else if let postAuthor = news.articleUsername { + // Text("\(NewsItemView.relativeDateFormatter.localizedString(for: postDate, relativeTo: Date.now))") Text(postAuthor) .foregroundStyle(.secondary) .truncationMode(.tail) -// .frame(maxWidth: 50) + // .frame(maxWidth: 50) .font(.caption) .lineLimit(1) } @@ -90,7 +88,7 @@ struct NewsItemView: View { @Observable class NewsItemSelection: Equatable { var selectedArticle: NewsInfo? = nil - + static func == (lhs: NewsItemSelection, rhs: NewsItemSelection) -> Bool { return lhs.selectedArticle == rhs.selectedArticle } @@ -99,25 +97,24 @@ class NewsItemSelection: Equatable { struct NewsView: View { @Environment(Hotline.self) private var model: Hotline @Environment(\.colorScheme) var colorScheme - + @State private var fetched = false @State private var selectedCategory: NewsInfo? = nil @State private var topListHeight: CGFloat = 280 @State private var dividerHeight: CGFloat = 30 - + @State private var articleSelection = NewsItemSelection() @State private var articleText = "" - -// @State private var selectedArticleID: UInt? - + + // @State private var selectedArticleID: UInt? + var articleList: some View { VStack(spacing: 0) { if model.news.count == 0 { Text("No News Available") .font(.headline) .opacity(0.3) - } - else { + } else { List(model.news) { category in NewsItemView(news: category) .frame(height: 38) @@ -128,10 +125,10 @@ struct NewsView: View { } .frame(maxWidth: .infinity, maxHeight: .infinity) .background(Color(uiColor: .systemGroupedBackground)) - + // .listStyle(.plain) } - + var body: some View { NavigationStack { VStack(spacing: 0) { @@ -140,19 +137,21 @@ struct NewsView: View { .frame(minHeight: topListHeight) .onChange(of: self.articleSelection.selectedArticle) { self.articleText = "" - if - let article = self.articleSelection.selectedArticle, + if let article = self.articleSelection.selectedArticle, let articleFlavor = article.articleFlavors?.first, - let articleID = article.articleID { + let articleID = article.articleID + { Task { - if let articleText = await self.model.getNewsArticle(id: articleID, at: article.path, flavor: articleFlavor) { + if let articleText = await self.model.getNewsArticle( + id: articleID, at: article.path, flavor: articleFlavor) + { self.articleText = articleText } } } -// print("SELECTED ARTICLE", articleSelection.selectedArticle?.name) + // print("SELECTED ARTICLE", articleSelection.selectedArticle?.name) } - + // Movable Divider VStack(alignment: .center) { Divider() @@ -165,7 +164,9 @@ struct NewsView: View { } Spacer() } - .background(colorScheme == .dark ? Color(white: 0.1) : Color(uiColor: UIColor.systemBackground)) + .background( + colorScheme == .dark ? Color(white: 0.1) : Color(uiColor: UIColor.systemBackground) + ) .frame(maxWidth: .infinity) .frame(height: dividerHeight) .gesture( @@ -175,11 +176,11 @@ struct NewsView: View { topListHeight = max(min(topListHeight + delta, 500), 50) } ) - + // Reader View ScrollView(.vertical) { VStack(alignment: .leading) { - + if let news = self.articleSelection.selectedArticle { if let poster = news.articleUsername, let postDate = news.articleDate { HStack(alignment: .firstTextBaseline) { @@ -189,7 +190,7 @@ struct NewsView: View { .lineLimit(1) .truncationMode(.tail) .textSelection(.enabled) -// .padding() + // .padding() Spacer() Text("\(NewsItemView.dateFormatter.string(from: postDate))") .foregroundStyle(.secondary) @@ -198,16 +199,16 @@ struct NewsView: View { .textSelection(.enabled) } .padding(.bottom, 8) - + Divider() .padding(.bottom, 16) } - + Text(news.name).font(.title3).fontWeight(.medium) .textSelection(.enabled) .padding(.bottom, 8) } - + Text(self.articleText) .multilineTextAlignment(.leading) .textSelection(.enabled) @@ -216,7 +217,8 @@ struct NewsView: View { .padding() } .scrollBounceBehavior(.basedOnSize) - .background(colorScheme == .dark ? Color(white: 0.1) : Color(uiColor: UIColor.systemBackground)) + .background( + colorScheme == .dark ? Color(white: 0.1) : Color(uiColor: UIColor.systemBackground)) } .task { if !fetched { diff --git a/Hotline/iOS/ServerView.swift b/Hotline/iOS/ServerView.swift index 1ce0a9c..11f57aa 100644 --- a/Hotline/iOS/ServerView.swift +++ b/Hotline/iOS/ServerView.swift @@ -3,11 +3,11 @@ import SwiftUI struct ServerView: View { @Environment(Hotline.self) private var model: Hotline @Environment(\.colorScheme) var colorScheme - + enum Tab { case chat, users, news, messageBoard, files } - + var body: some View { TabView { ChatView() @@ -15,13 +15,13 @@ struct ServerView: View { Image(systemName: "bubble") } .tag(Tab.chat) - + UsersView() .tabItem { Image(systemName: "person.2") } .tag(Tab.users) - + if let v = model.serverVersion, v >= 150 { NewsView() .tabItem { @@ -29,13 +29,13 @@ struct ServerView: View { } .tag(Tab.news) } - + MessageBoardView() .tabItem { Image(systemName: "note.text") } .tag(Tab.messageBoard) - + FilesView() .tabItem { Image(systemName: "folder").tint(.black) diff --git a/Hotline/iOS/TrackerView.swift b/Hotline/iOS/TrackerView.swift index 2a3583b..43b1916 100644 --- a/Hotline/iOS/TrackerView.swift +++ b/Hotline/iOS/TrackerView.swift @@ -4,13 +4,13 @@ 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 - + // @State private var connecting = false + func connectionStatusToProgress(status: HotlineClientStatus) -> Double { switch status { case .disconnected: @@ -25,118 +25,126 @@ struct TrackerConnectView: View { return 1.0 } } - + var body: some View { - VStack(alignment: .leading) { - if self.model.status == .disconnected { - 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") + VStack(alignment: .leading) { + if self.model.status == .disconnected { + 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) } - .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: nil, description: nil, address: address, port: HotlinePorts.DefaultServerPort, users: 0, login: login, password: password) - server = s - self.model.login(server: s, username: "bolt", iconID: 128) { success in - if !success { - print("FAILED LOGIN??") - } - else { - self.model.sendUserInfo(username: "bolt", iconID: 128) - self.model.getUserList() - } + 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: nil, description: nil, address: address, port: HotlinePorts.DefaultServerPort, + users: 0, login: login, password: password) + server = s + self.model.login(server: s, username: "bolt", iconID: 128) { success in + if !success { + print("FAILED LOGIN??") + } else { + self.model.sendUserInfo(username: "bolt", iconID: 128) + self.model.getUserList() } - } label: { - Text("Connect") } - .disabled(self.model.status != .disconnected) - .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) + } label: { + Text("Connect") } - .padding() + .disabled(self.model.status != .disconnected) + .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() - .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) -// } + } + .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) - } + } + .toolbar { + ToolbarItem(placement: .principal) { + Text("Connect to Server") + .font(.headline) } -// .presentationBackground(.regularMaterial, in: Color(uiColor: .systemGroupedBackground)) + } + // .presentationBackground(.regularMaterial, in: Color(uiColor: .systemGroupedBackground)) .presentationBackground { Color.clear .background(Material.regular) @@ -151,7 +159,7 @@ struct TrackerConnectView: View { struct TrackerView: View { @Environment(Hotline.self) private var model: Hotline @Environment(\.colorScheme) var colorScheme - + @State private var servers: [Server] = [] @State private var selectedServer: Server? @State private var scrollOffset: CGFloat = CGFloat.zero @@ -161,15 +169,15 @@ struct TrackerView: View { @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 { return false } - + return desc.count > 0 && desc != server.name } - + func connectionStatusToProgress(status: HotlineClientStatus) -> Double { switch status { case .disconnected: @@ -184,21 +192,21 @@ struct TrackerView: View { return 1.0 } } - + func inverseLerp(lower: Double, upper: Double, v: Double) -> Double { return (v - lower) / (upper - lower) } - + func updateServers() async { -// "hltracker.com" -// "tracker.preterhuman.net" -// "hotline.ubersoft.org" -// "tracked.nailbat.com" -// "hotline.duckdns.org" -// "tracked.agent79.org" + // "hltracker.com" + // "tracker.preterhuman.net" + // "hotline.ubersoft.org" + // "tracked.nailbat.com" + // "hotline.duckdns.org" + // "tracked.agent79.org" self.servers = await model.getServerList(tracker: "hltracker.com") } - + var body: some View { ZStack(alignment: .center) { VStack(alignment: .center) { @@ -249,7 +257,7 @@ struct TrackerView: View { .frame(height: 40.0) } .padding() - + Spacer() } .opacity(inverseLerp(lower: -50, upper: 0, v: scrollOffset)) @@ -269,7 +277,8 @@ struct TrackerView: View { Text(server.description!).opacity(0.5).font(.system(size: 16)) } Spacer() - Text("\(server.address):" + String(format: "%i", server.port)).opacity(0.3).font(.system(size: 13)) + Text("\(server.address):" + String(format: "%i", server.port)).opacity(0.3).font( + .system(size: 13)) } Spacer() if server.users > 0 { @@ -278,19 +287,17 @@ struct TrackerView: View { } if server == selectedServer { Spacer(minLength: 16) - + 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 { + } else { Button("Connect") { self.model.login(server: server, username: "bolt", iconID: 128) { success in if !success { print("FAILED LOGIN??") - } - else { + } else { self.model.sendUserInfo(username: "bolt", iconID: 128) self.model.getUserList() self.model.downloadBanner() @@ -302,13 +309,17 @@ struct TrackerView: View { .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) + 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) + RoundedRectangle(cornerRadius: 10.0).stroke(.black, lineWidth: 3).opacity( + colorScheme == .dark ? 0.0 : 0.2) ) .cornerRadius(10.0) } @@ -346,22 +357,24 @@ struct TrackerView: View { } 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 (connectDismissed && serverVisible) }, set: { _ in }), onDismiss: { - model.disconnect() - }) { + .fullScreenCover( + isPresented: Binding(get: { return (connectDismissed && serverVisible) }, set: { _ in }), + onDismiss: { + model.disconnect() + } + ) { ServerView() } .onChange(of: model.status) { @@ -377,26 +390,27 @@ struct TrackerView: View { guard url.scheme == "hotline" else { return } - + if let address = url.host() { let login = url.user(percentEncoded: false) ?? "" let password = url.password(percentEncoded: false) ?? "" let port = url.port ?? HotlinePorts.DefaultServerPort - + self.model.disconnect() - - let tempServer = Server(name: nil, description: nil, address: address, port: port, users: 0, login: login, password: password) + + let tempServer = Server( + name: nil, description: nil, address: address, port: port, users: 0, login: login, + password: password) self.model.login(server: tempServer, username: "bolt", iconID: 128) { success in if !success { print("FAILED LOGIN??") - } - else { + } else { self.model.sendUserInfo(username: "bolt", iconID: 128) self.model.getUserList() self.model.downloadBanner() } } - + // TODO: Find a better way to show login status when trying to connect outside of the Tracker server list. Perhaps this opens the connect sheet prefilled. } }) diff --git a/Hotline/iOS/UsersView.swift b/Hotline/iOS/UsersView.swift index 5d7a198..e1297c8 100644 --- a/Hotline/iOS/UsersView.swift +++ b/Hotline/iOS/UsersView.swift @@ -2,7 +2,7 @@ import SwiftUI struct UsersView: View { @Environment(Hotline.self) private var model: Hotline - + var body: some View { NavigationStack { List(model.users) { u in |