aboutsummaryrefslogtreecommitdiff
path: root/Hotline/Views
diff options
context:
space:
mode:
authorDustin Mierau <dustin@mierau.me>2023-12-16 09:16:15 -0800
committerDustin Mierau <dustin@mierau.me>2023-12-16 09:16:15 -0800
commit3e4fbdfcab4a4d2435aed27a16131a6ca26d7408 (patch)
treea1aec47c2de30074257dec14e3b2615a8b178033 /Hotline/Views
parenta428e3e28fb851cec65ff27f212c19bce08e5369 (diff)
Implemented basic news reading support. Various UI tweaks.
Diffstat (limited to 'Hotline/Views')
-rw-r--r--Hotline/Views/ChatView.swift5
-rw-r--r--Hotline/Views/FilesView.swift2
-rw-r--r--Hotline/Views/MessageBoardView.swift2
-rw-r--r--Hotline/Views/NewsView.swift188
-rw-r--r--Hotline/Views/TrackerView.swift8
-rw-r--r--Hotline/Views/UsersView.swift2
6 files changed, 142 insertions, 65 deletions
diff --git a/Hotline/Views/ChatView.swift b/Hotline/Views/ChatView.swift
index 8e5b135..e8c7754 100644
--- a/Hotline/Views/ChatView.swift
+++ b/Hotline/Views/ChatView.swift
@@ -32,7 +32,7 @@ struct ChatView: View {
.opacity(0.75)
HStack {
Spacer()
- Text((model.server?.name ?? "") + " Server Agreement")
+ Text((model.serverTitle) + " Server Agreement")
.font(.caption)
.fontWeight(.medium)
.opacity(0.4)
@@ -78,6 +78,7 @@ struct ChatView: View {
}
.padding(.bottom, 12)
}
+ .defaultScrollAnchor(.bottom)
.onChange(of: model.chat.count) {
withAnimation {
reader.scrollTo(bottomID, anchor: .bottom)
@@ -127,7 +128,7 @@ struct ChatView: View {
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .principal) {
- Text(model.server?.name ?? "")
+ Text(model.serverTitle)
.font(.headline)
}
ToolbarItem(placement: .navigationBarLeading) {
diff --git a/Hotline/Views/FilesView.swift b/Hotline/Views/FilesView.swift
index 5cbf0c9..8ad3837 100644
--- a/Hotline/Views/FilesView.swift
+++ b/Hotline/Views/FilesView.swift
@@ -116,7 +116,7 @@ struct FilesView: View {
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .principal) {
- Text(model.server?.name ?? "")
+ Text(model.serverTitle)
.font(.headline)
}
ToolbarItem(placement: .navigationBarLeading) {
diff --git a/Hotline/Views/MessageBoardView.swift b/Hotline/Views/MessageBoardView.swift
index 8a1c831..0d3968f 100644
--- a/Hotline/Views/MessageBoardView.swift
+++ b/Hotline/Views/MessageBoardView.swift
@@ -42,7 +42,7 @@ struct MessageBoardView: View {
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .principal) {
- Text(model.server?.name ?? "")
+ Text(model.serverTitle)
.font(.headline)
}
ToolbarItem(placement: .navigationBarLeading) {
diff --git a/Hotline/Views/NewsView.swift b/Hotline/Views/NewsView.swift
index ad7904e..bd3ae1c 100644
--- a/Hotline/Views/NewsView.swift
+++ b/Hotline/Views/NewsView.swift
@@ -1,58 +1,142 @@
import SwiftUI
+import UniformTypeIdentifiers
-struct NewsView: View {
+
+
+struct NewsItemView: View {
@Environment(Hotline.self) private var model: Hotline
- @Environment(\.colorScheme) var colorScheme
+ @Environment(NewsItemSelection.self) private var selectedArticle: NewsItemSelection
- @State private var fetched = false
- @State private var selectedCategory: NewsCategory? = nil
- @State private var topListHeight: CGFloat = 200
- @State private var dividerHeight: CGFloat = 30
+ let news: NewsInfo
- var articleList: some View {
-
- // Your list content goes here
- List {
- ForEach(model.news, id: \.self) { category in
- DisclosureGroup {
- ProgressView(value: 0.4)
- .task {
- print("EXPANDED?", category.name)
-// hotline.sendGetNewsArticles(path: [cat.name]) {
-// print("OK")
-// }
- }
- } label: {
- Text(category.name)
+ @State var expanded = false
+
+ var body: some View {
+ if news.count > 0 {
+ DisclosureGroup(isExpanded: $expanded) {
+ ForEach(news.children) { childNews in
+ NewsItemView(news: childNews)
+ .environment(self.selectedArticle)
+ .frame(height: 38)
+ }
+ } label: {
+ HStack {
+ if news.type == .bundle {
+ Text(Image(systemName: "tray.2.fill"))
+ }
+ else {
+ Text(Image(systemName: "tray.full.fill"))
+ }
+ Text(news.name)
.fontWeight(.medium)
.lineLimit(1)
.truncationMode(.tail)
+ Spacer()
+ if news.count > 0 {
+ Text("\(news.count)")
+ .foregroundStyle(.secondary)
+ }
+ }
+ }
+ .onChange(of: expanded) {
+ if !expanded {
+ return
+ }
+
+ Task {
+ await model.getNewsList(at: news.path)
}
}
}
- .scrollBounceBehavior(.basedOnSize)
-// .listStyle(.plain)
- }
-
- var readerView: some View {
- // Your list content goes here
- ScrollView(.vertical) {
- HStack(alignment: .top, spacing: 0) {
- Text("HELLO")
- .multilineTextAlignment(.leading)
+ else {
+ HStack {
+ Text(Image(systemName: "doc.text"))
+ Text(news.name)
+ .fontWeight(.medium)
+ .lineLimit(1)
+ .truncationMode(.tail)
Spacer()
+ if news.count > 0 {
+ Text("\(news.count)")
+ .foregroundStyle(.secondary)
+ }
+ }
+ .onTapGesture {
+ if news.type == .article {
+ print("SELECTED", news.name)
+ selectedArticle.selectedArticle = news
+ }
}
- .padding()
}
- .scrollBounceBehavior(.basedOnSize)
- .background(colorScheme == .dark ? Color(white: 0.1) : Color(uiColor: UIColor.systemBackground))
}
+}
+
+@Observable
+class NewsItemSelection: Equatable {
+ var selectedArticle: NewsInfo? = nil
+ static func == (lhs: NewsItemSelection, rhs: NewsItemSelection) -> Bool {
+ return lhs.selectedArticle == rhs.selectedArticle
+ }
+}
+
+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 = 200
+ @State private var dividerHeight: CGFloat = 30
+
+ @State private var articleSelection = NewsItemSelection()
+ @State private var articleText = ""
+// @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 {
+ List(model.news) { category in
+ NewsItemView(news: category)
+ .environment(self.articleSelection)
+ .frame(height: 38)
+ }
+ .scrollBounceBehavior(.basedOnSize)
+ }
+ }
+ .frame(maxWidth: .infinity, maxHeight: .infinity)
+ .background(Color(uiColor: .systemGroupedBackground))
+
+ // .listStyle(.plain)
+ }
+
var body: some View {
NavigationStack {
VStack(spacing: 0) {
articleList
.frame(height: topListHeight)
+ .frame(minHeight: topListHeight)
+ .onChange(of: self.articleSelection.selectedArticle) {
+ self.articleText = ""
+ if
+ let article = self.articleSelection.selectedArticle,
+ let articleFlavor = article.articleFlavors?.first,
+ let articleID = article.articleID {
+ Task {
+ if let articleText = await self.model.getNewsArticle(id: articleID, at: article.path, flavor: articleFlavor) {
+ self.articleText = articleText
+ }
+ }
+ }
+// print("SELECTED ARTICLE", articleSelection.selectedArticle?.name)
+ }
+
+ // Movable Divider
VStack(alignment: .center) {
Divider()
Spacer()
@@ -72,28 +156,31 @@ struct NewsView: View {
.onChanged { gesture in
let delta = gesture.translation.height
topListHeight = max(min(topListHeight + delta, 500), 50)
- // bottomListHeight = max(min(bottomListHeight - delta, 400), 0)
}
)
- readerView
+
+ // Reader View
+ ScrollView(.vertical) {
+ HStack(alignment: .top, spacing: 0) {
+ Text(self.articleText)
+ .multilineTextAlignment(.leading)
+ Spacer()
+ }
+ .padding()
+ }
+ .scrollBounceBehavior(.basedOnSize)
+ .background(colorScheme == .dark ? Color(white: 0.1) : Color(uiColor: UIColor.systemBackground))
}
.task {
if !fetched {
- let _ = await model.getNewsCategories()
+ let _ = await model.getNewsList()
fetched = true
-
- // hotline.sendGetNewsArticles(path: ["News"]) {
- // print("GOT ARTICLES?")
- // }
}
}
- // .refreshable {
- // hotline.sendGetNewsCategories()
- // }
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .principal) {
- Text(model.server?.name ?? "")
+ Text(model.serverTitle)
.font(.headline)
}
ToolbarItem(placement: .navigationBarLeading) {
@@ -106,19 +193,8 @@ struct NewsView: View {
.foregroundColor(.secondary)
}
}
-// ToolbarItem(placement: .navigationBarTrailing) {
-// Button {
-//
-// } label: {
-// Image(systemName: "square.and.pencil")
-// // .symbolRenderingMode(.hierarchical)
-// // .foregroundColor(.secondary)
-// }
-//
-// }
}
}
-
}
}
diff --git a/Hotline/Views/TrackerView.swift b/Hotline/Views/TrackerView.swift
index acb2069..6204fd2 100644
--- a/Hotline/Views/TrackerView.swift
+++ b/Hotline/Views/TrackerView.swift
@@ -86,7 +86,7 @@ struct TrackerConnectView: View {
)
.cornerRadius(10.0)
Button {
- let s = Server(name: address, description: nil, address: address, port: Server.defaultPort, users: 0)
+ let s = Server(name: nil, description: nil, address: address, port: Server.defaultPort, users: 0)
server = s
connecting = true
Task {
@@ -200,7 +200,7 @@ struct TrackerView: View {
// "tracked.nailbat.com"
// "hotline.duckdns.org"
// "tracked.agent79.org"
- self.servers = await model.getServers(address: "hltracker.com")
+ self.servers = await model.getServerList(tracker: "hltracker.com")
}
var body: some View {
@@ -267,7 +267,7 @@ struct TrackerView: View {
HStack(alignment: .firstTextBaseline) {
Image(systemName: "globe.americas.fill").font(.title3)
VStack(alignment: .leading) {
- Text(server.name).font(.title3).fontWeight(.medium)
+ Text(server.name ?? server.address).font(.title3).fontWeight(.medium)
if shouldDisplayDescription(server: server) {
Spacer()
Text(server.description!).opacity(0.5).font(.system(size: 16))
@@ -382,7 +382,7 @@ struct TrackerView: View {
Task {
model.disconnect()
- let _ = await model.login(server: Server(name: address, description: nil, address: address, port: port, users: 0), login: login, password: password, username: "bolt", iconID: 128)
+ let _ = await model.login(server: Server(name: nil, description: nil, address: address, port: port, users: 0), login: login, password: password, username: "bolt", iconID: 128)
}
// 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/Views/UsersView.swift b/Hotline/Views/UsersView.swift
index f923ff4..d1f3318 100644
--- a/Hotline/Views/UsersView.swift
+++ b/Hotline/Views/UsersView.swift
@@ -17,7 +17,7 @@ struct UsersView: View {
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .principal) {
- Text(model.server?.name ?? "")
+ Text(model.serverTitle)
.font(.headline)
}
ToolbarItem(placement: .navigationBarLeading) {