diff options
| author | Dustin Mierau <dustin@mierau.me> | 2023-12-06 22:52:09 -0800 |
|---|---|---|
| committer | Dustin Mierau <dustin@mierau.me> | 2023-12-06 22:52:09 -0800 |
| commit | e3392bb948ad53889ad334140952f2acf614668e (patch) | |
| tree | 74937a9202b3bb71f28ef9d8e0b3560bdd195b49 /Hotline/Views | |
| parent | 195af38221d1a4358455ba8501b87e4098da101b (diff) | |
Some work on news. More UI tweaks across the board.
Diffstat (limited to 'Hotline/Views')
| -rw-r--r-- | Hotline/Views/ChatView.swift | 6 | ||||
| -rw-r--r-- | Hotline/Views/FilesView.swift | 2 | ||||
| -rw-r--r-- | Hotline/Views/NewsView.swift | 89 | ||||
| -rw-r--r-- | Hotline/Views/TrackerView.swift | 148 | ||||
| -rw-r--r-- | Hotline/Views/UserListView.swift | 16 |
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) { |