aboutsummaryrefslogtreecommitdiff
path: root/Hotline/Views
diff options
context:
space:
mode:
authorDustin Mierau <dustin@mierau.me>2023-12-06 22:52:09 -0800
committerDustin Mierau <dustin@mierau.me>2023-12-06 22:52:09 -0800
commite3392bb948ad53889ad334140952f2acf614668e (patch)
tree74937a9202b3bb71f28ef9d8e0b3560bdd195b49 /Hotline/Views
parent195af38221d1a4358455ba8501b87e4098da101b (diff)
Some work on news. More UI tweaks across the board.
Diffstat (limited to 'Hotline/Views')
-rw-r--r--Hotline/Views/ChatView.swift6
-rw-r--r--Hotline/Views/FilesView.swift2
-rw-r--r--Hotline/Views/NewsView.swift89
-rw-r--r--Hotline/Views/TrackerView.swift148
-rw-r--r--Hotline/Views/UserListView.swift16
5 files changed, 182 insertions, 79 deletions
diff --git a/Hotline/Views/ChatView.swift b/Hotline/Views/ChatView.swift
index dc6e1d4..1aee6b2 100644
--- a/Hotline/Views/ChatView.swift
+++ b/Hotline/Views/ChatView.swift
@@ -2,6 +2,7 @@ import SwiftUI
struct ChatView: View {
@Environment(HotlineClient.self) private var hotline
+ @Environment(\.colorScheme) var colorScheme
@State var input: String = ""
@State private var scrollPos: Int?
@@ -17,13 +18,12 @@ struct ChatView: View {
LazyVStack(alignment: .leading) {
ForEach(hotline.chatMessages) { msg in
if msg.type == .agreement {
-
VStack(alignment: .leading) {
Text(msg.text)
.padding()
.opacity(0.75)
- .background(Color(white: 0.96))
- .cornerRadius(20)
+ .background(colorScheme == .dark ? Color(white: 0.1) : Color(white: 0.96))
+ .cornerRadius(16)
}
.padding()
}
diff --git a/Hotline/Views/FilesView.swift b/Hotline/Views/FilesView.swift
index 1b35695..3b2b236 100644
--- a/Hotline/Views/FilesView.swift
+++ b/Hotline/Views/FilesView.swift
@@ -57,6 +57,8 @@ struct FilesView: View {
else {
HStack(alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/) {
Image(uiImage: fileIcon(name: tree.name))
+ .renderingMode(.template)
+ .foregroundColor(.accentColor)
}
.frame(minWidth: 25)
Text(tree.name).bold()
diff --git a/Hotline/Views/NewsView.swift b/Hotline/Views/NewsView.swift
index 5f2dbe9..9c4d34a 100644
--- a/Hotline/Views/NewsView.swift
+++ b/Hotline/Views/NewsView.swift
@@ -5,32 +5,89 @@ struct NewsView: View {
@Environment(HotlineClient.self) private var hotline
@State private var fetched = false
+ @State private var selectedCategory: HotlineNewsCategory? = nil
+ @State private var topListHeight: CGFloat = 200
+ @State private var dividerHeight: CGFloat = 30
+
+ var topList: some View {
+
+ // Your list content goes here
+ List {
+ ForEach(hotline.newsCategories, id: \.self) { cat in
+ DisclosureGroup {
+ ProgressView(value: 0.4)
+ .task {
+ print("EXPANDED?", cat.name)
+ hotline.sendGetNewsArticles(path: [cat.name]) {
+ print("OK")
+ }
+ }
+ } label: {
+ Text(cat.name)
+ .fontWeight(.medium)
+ .lineLimit(1)
+ .truncationMode(.tail)
+ }
+ }
+ }
+// .listStyle(.plain)
+ }
+
+ var bottomList: some View {
+ // Your list content goes here
+ ScrollView(.vertical) {
+ HStack(alignment: .top, spacing: 0) {
+ Text("HELLO")
+ .multilineTextAlignment(.leading)
+ Spacer()
+ }
+ .padding()
+ }
+ }
var body: some View {
-// @Bindable var config = appState
NavigationStack {
- ScrollView {
- LazyVStack(alignment: .leading) {
-// ForEach(hotline.messageBoardMessages, id: \.self) {
-// Text($0)
-// .lineLimit(100)
-// .padding()
-// .textSelection(.enabled)
-// Divider()
-// }
+ VStack(spacing: 0) {
+ topList
+ .frame(height: topListHeight)
+ VStack(alignment: .center) {
+ Divider()
+ Spacer()
+ HStack(alignment: .center) {
+ Image(systemName: "line.3.horizontal")
+ .opacity(0.2)
+ .font(.system(size: 14))
+ }
+ Spacer()
+// Divider()
}
- Spacer()
+ .background(Color(uiColor: UIColor.systemBackground))
+ .frame(maxWidth: .infinity)
+ .frame(height: dividerHeight)
+ .gesture(
+ DragGesture()
+ .onChanged { gesture in
+ let delta = gesture.translation.height
+ topListHeight = max(min(topListHeight + delta, 500), 50)
+ // bottomListHeight = max(min(bottomListHeight - delta, 400), 0)
+ }
+ )
+ bottomList
}
.task {
if !fetched {
hotline.sendGetNewsCategories() {
fetched = true
}
+
+ // hotline.sendGetNewsArticles(path: ["News"]) {
+ // print("GOT ARTICLES?")
+ // }
}
}
- .refreshable {
- hotline.sendGetNewsCategories()
- }
+ // .refreshable {
+ // hotline.sendGetNewsCategories()
+ // }
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .principal) {
@@ -52,8 +109,8 @@ struct NewsView: View {
} label: {
Image(systemName: "square.and.pencil")
-// .symbolRenderingMode(.hierarchical)
-// .foregroundColor(.secondary)
+ // .symbolRenderingMode(.hierarchical)
+ // .foregroundColor(.secondary)
}
}
diff --git a/Hotline/Views/TrackerView.swift b/Hotline/Views/TrackerView.swift
index 3ed66dd..7f59118 100644
--- a/Hotline/Views/TrackerView.swift
+++ b/Hotline/Views/TrackerView.swift
@@ -11,6 +11,7 @@ struct TrackerView: View {
@Environment(\.colorScheme) var colorScheme
@State private var selectedServer: HotlineServer?
+ @State var scrollOffset: CGFloat = CGFloat.zero
func shouldDisplayDescription(server: HotlineServer) -> Bool {
guard let name = server.name, let desc = server.description else {
@@ -36,83 +37,126 @@ struct TrackerView: View {
}
}
+ func inverseLerp(lower: Double, upper: Double, v: Double) -> Double {
+ return (v - lower) / (upper - lower)
+ }
+
var body: some View {
@Bindable var config = appState
@Bindable var client = hotline
- ScrollView {
- LazyVStack(alignment: .leading) {
- ForEach(tracker.servers) { server in
- VStack(alignment: .leading) {
- HStack(alignment: .firstTextBaseline) {
- Image(systemName: "globe.americas.fill").font(.title3)
- VStack(alignment: .leading) {
- Text(server.name!).font(.title3).fontWeight(.medium)
- if shouldDisplayDescription(server: server) {
+ ZStack(alignment: .center) {
+ VStack(alignment: .center) {
+ ZStack(alignment: .top) {
+ Image("Hotline")
+ .resizable()
+ .renderingMode(.template)
+ .foregroundColor(Color(hex: 0xE10000))
+ .scaledToFit()
+ .frame(width: 40.0, height: 40.0)
+ HStack(alignment: .center) {
+ Spacer()
+ Button {
+ // hotline.disconnect()
+ } label: {
+ Text(Image(systemName: "point.3.connected.trianglepath.dotted"))
+ .symbolRenderingMode(.hierarchical)
+ .foregroundColor(.primary)
+ .font(.title2)
+ .padding(.trailing, 16)
+ }
+ }
+ .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()
+ }
+ ObservableScrollView(scrollOffset: $scrollOffset) {
+ LazyVStack(alignment: .leading) {
+ ForEach(tracker.servers) { server in
+ VStack(alignment: .leading) {
+ HStack(alignment: .firstTextBaseline) {
+ Image(systemName: "globe.americas.fill").font(.title3)
+ VStack(alignment: .leading) {
+ Text(server.name!).font(.title3).fontWeight(.medium)
+ if shouldDisplayDescription(server: server) {
+ Spacer()
+ Text(server.description!).opacity(0.5).font(.system(size: 16))
+ }
Spacer()
- Text(server.description!).opacity(0.4).font(.system(size: 16))
+ Text("\(server.address)").opacity(0.3).font(.system(size: 13))
}
Spacer()
- Text("\(server.address)").opacity(0.2).font(.system(size: 13))
- }
- Spacer()
- Text("\(server.users)").opacity(0.2).font(.system(size: 16)).fontWeight(.medium)
- }
- if server == selectedServer {
- Spacer(minLength: 16)
-
- if hotline.server == server && hotline.connectionStatus != .disconnected {
- ProgressView("", value: connectionStatusToProgress(status: hotline.connectionStatus))
+ Text("\(server.users)").opacity(0.3).font(.system(size: 16)).fontWeight(.medium)
}
- else {
- Button("Connect") {
- hotline.connect(to: server)
+ if server == selectedServer {
+ Spacer(minLength: 16)
+
+ if hotline.server == server && hotline.connectionStatus != .disconnected {
+ ProgressView(value: connectionStatusToProgress(status: hotline.connectionStatus))
+ .frame(minHeight: 10)
+ .accentColor(colorScheme == .dark ? .white : .black)
+ }
+ else {
+ Button("Connect") {
+ hotline.connect(to: server)
+ }
+ .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)
}
- .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)
}
}
- }
- .multilineTextAlignment(.leading)
- .padding()
- .background(colorScheme == .dark ? Color(white: 0.1) : .white)
- .cornerRadius(20)
- .shadow(color: Color(white: 0.0, opacity: 0.1), radius: 16, x: 0, y: 10)
- .onTapGesture {
- withAnimation(.bouncy(duration: 0.25, extraBounce: 0.2)) {
- selectedServer = server
+ .multilineTextAlignment(.leading)
+ .padding()
+ .background(colorScheme == .dark ? Color(white: 0.12) : .white)
+ .cornerRadius(16)
+ .shadow(color: Color(white: 0.0, opacity: 0.1), radius: 16, x: 0, y: 10)
+ .onTapGesture {
+ withAnimation(.bouncy(duration: 0.25, extraBounce: 0.2)) {
+ selectedServer = server
+ }
}
}
+ .padding(EdgeInsets(top: 4, leading: 16, bottom: 4, trailing: 16))
+ }
+ .padding(EdgeInsets(top: 75, leading: 0, bottom: 0, trailing: 0))
+ }
+ .refreshable {
+ await withCheckedContinuation { continuation in
+ tracker.fetch() {
+ continuation.resume()
+ }
}
- .padding(EdgeInsets(top: 4, leading: 16, bottom: 4, trailing: 16))
}
+
}
.fullScreenCover(isPresented: Binding(get: { return hotline.connectionStatus == .loggedIn }, set: { _ in }), onDismiss: {
hotline.disconnect()
}) {
ServerView()
}
- .background(colorScheme == .dark ? .black : Color(white: 0.95))
+ .background(Color(uiColor: UIColor.systemGroupedBackground))
.frame(maxWidth: .infinity)
.task {
tracker.fetch()
}
- .refreshable {
- await withCheckedContinuation { continuation in
- tracker.fetch() {
- continuation.resume()
- }
- }
- }
- .navigationTitle("Tracker")
- .navigationBarTitleDisplayMode(.inline)
}
}
diff --git a/Hotline/Views/UserListView.swift b/Hotline/Views/UserListView.swift
index cae1d0c..e0fa7fb 100644
--- a/Hotline/Views/UserListView.swift
+++ b/Hotline/Views/UserListView.swift
@@ -5,15 +5,15 @@ struct UserListView: View {
var body: some View {
NavigationStack {
- VStack(spacing: 0) {
- List(hotline.userList) { u in
- HStack(alignment: .firstTextBaseline) {
- Text(u.name).bold().foregroundStyle(u.isAdmin ? Color.red : Color.black).opacity(u.isIdle ? 0.5 : 1.0)
- }
- }
- .listStyle(.plain)
- .padding()
+ List(hotline.userList) { u in
+ Text(u.name)
+ .fontWeight(.medium)
+ .lineLimit(1)
+ .truncationMode(.tail)
+ .foregroundStyle(u.isAdmin ? Color(hex: 0xE10000) : Color.accentColor)
+ .opacity(u.isIdle ? 0.5 : 1.0)
}
+// .listStyle(.grouped)
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .principal) {