aboutsummaryrefslogtreecommitdiff
path: root/Hotline/macOS
diff options
context:
space:
mode:
authorDustin Mierau <dustin@mierau.me>2024-05-13 14:12:42 -0700
committerDustin Mierau <dustin@mierau.me>2024-05-13 14:12:42 -0700
commitf04aef1044687253fbc56a0db0f3a905540eb03d (patch)
treebde1890ba122d7a04a3cde98fb5fd053ca181a9d /Hotline/macOS
parent67050d06a3bc2d28e969cf1388eafa95400c35a3 (diff)
Refined news and file listing. Tweaked news icons. New tracker window icons. New server toolbar globe icon. Fixing disabling of toolbar buttons in files.
Diffstat (limited to 'Hotline/macOS')
-rw-r--r--Hotline/macOS/FilesView.swift43
-rw-r--r--Hotline/macOS/NewsItemView.swift135
-rw-r--r--Hotline/macOS/NewsView.swift114
-rw-r--r--Hotline/macOS/ServerView.swift14
-rw-r--r--Hotline/macOS/TrackerView.swift19
5 files changed, 185 insertions, 140 deletions
diff --git a/Hotline/macOS/FilesView.swift b/Hotline/macOS/FilesView.swift
index 133e1fd..e3f5118 100644
--- a/Hotline/macOS/FilesView.swift
+++ b/Hotline/macOS/FilesView.swift
@@ -11,7 +11,7 @@ struct FileView: View {
let depth: Int
var body: some View {
- HStack {
+ HStack(alignment: .center, spacing: 0) {
if file.isFolder {
Button {
if file.isFolder {
@@ -26,16 +26,20 @@ struct FileView: View {
.buttonStyle(.plain)
.frame(width: 10)
.padding(.leading, 4)
+ .padding(.trailing, 8)
}
else {
- HStack {
-
- }.frame(width: 10)
+ Spacer()
+ .frame(width: 10)
.padding(.leading, 4)
+ .padding(.trailing, 8)
}
+
HStack(alignment: .center) {
if file.isUnavailable {
- Image(systemName: "questionmark.app.fill").opacity(0.5)
+ Image(systemName: "questionmark.app.fill")
+ .frame(width: 16, height: 16)
+ .opacity(0.5)
}
else if file.isFolder {
FolderIconView()
@@ -46,8 +50,13 @@ struct FileView: View {
.frame(width: 16, height: 16)
}
}
- .frame(width: 15)
- Text(file.name).lineLimit(1).truncationMode(.tail).opacity(file.isUnavailable ? 0.5 : 1.0)
+ .frame(width: 16)
+ .padding(.trailing, 6)
+
+ Text(file.name)
+ .lineLimit(1)
+ .truncationMode(.tail)
+ .opacity(file.isUnavailable ? 0.5 : 1.0)
if file.isFolder && loading {
ProgressView().controlSize(.small).padding([.leading, .trailing], 1)
@@ -55,9 +64,10 @@ struct FileView: View {
Spacer()
if !file.isUnavailable {
if file.isFolder {
- Text("^[\(file.fileSize) file](inflect: true)")
+ Text("^[\(file.fileSize) \("file")](inflect: true)")
.foregroundStyle(.secondary)
.lineLimit(1)
+ .padding(.trailing, 6)
}
else {
Text(formattedFileSize(file.fileSize)).foregroundStyle(.secondary).lineLimit(1)
@@ -185,9 +195,10 @@ struct FilesView: View {
ToolbarItem(placement: .primaryAction) {
Button {
} label: {
- Label("Delete File", systemImage: "trash")
+ Label("Delete", systemImage: "trash")
}
.help("Delete")
+ .disabled(true)
}
ToolbarItem(placement: .primaryAction) {
@@ -200,10 +211,10 @@ struct FilesView: View {
}
}
} label: {
- Label("Preview File", systemImage: "eye")
+ Label("Preview", systemImage: "eye")
}
- .help("Preview File")
- .disabled(selection?.isPreviewable == false)
+ .help("Preview")
+ .disabled(selection == nil || selection?.isPreviewable == false)
}
ToolbarItem(placement: .primaryAction) {
@@ -214,9 +225,10 @@ struct FilesView: View {
}
}
} label: {
- Label("Get File Info", systemImage: "info.circle")
+ Label("Get Info", systemImage: "info.circle")
}
- .help("Get File Info")
+ .help("Get Info")
+ .disabled(selection == nil)
}
ToolbarItem(placement: .primaryAction) {
@@ -225,9 +237,10 @@ struct FilesView: View {
model.downloadFile(s.name, path: s.path)
}
} label: {
- Label("Download File", systemImage: "square.and.arrow.down")
+ Label("Download", systemImage: "arrow.down")
}
.help("Download")
+ .disabled(selection == nil || selection?.isFolder == true)
}
}
}
diff --git a/Hotline/macOS/NewsItemView.swift b/Hotline/macOS/NewsItemView.swift
new file mode 100644
index 0000000..5cd9ce4
--- /dev/null
+++ b/Hotline/macOS/NewsItemView.swift
@@ -0,0 +1,135 @@
+import SwiftUI
+
+struct NewsItemView: View {
+ @Environment(Hotline.self) private var model: Hotline
+
+ var news: NewsInfo
+ let depth: Int
+
+ static var dateFormatter: DateFormatter = {
+ var dateFormatter = DateFormatter()
+ dateFormatter.dateStyle = .long
+ dateFormatter.timeStyle = .short
+ dateFormatter.timeZone = .gmt
+ return dateFormatter
+ }()
+
+ static var relativeDateFormatter: RelativeDateTimeFormatter = {
+ var formatter = RelativeDateTimeFormatter()
+ formatter.unitsStyle = .full
+ formatter.dateTimeStyle = .named
+ formatter.formattingContext = .listItem
+ return formatter
+ }()
+
+ var body: some View {
+ HStack(alignment: .center, spacing: 0) {
+ if news.expandable {
+ Button {
+ news.expanded.toggle()
+ } label: {
+ Text(Image(systemName: news.expanded ? "chevron.down" : "chevron.right"))
+ .bold()
+ .font(.system(size: 10))
+ .opacity(0.5)
+ .frame(alignment: .center)
+ }
+ .buttonStyle(.plain)
+ .frame(width: 10)
+ .padding(.leading, 4)
+ .padding(.trailing, 8)
+ }
+ else {
+ Spacer()
+ .frame(width: 10)
+ .padding(.leading, 4)
+ .padding(.trailing, 8)
+ }
+
+ // Tree indent
+ Spacer()
+ .frame(width: (CGFloat(depth) * 22))
+
+ switch news.type {
+ case .category:
+ Image("News Category")
+ .resizable()
+ .frame(width: 16, height: 16, alignment: .center)
+ .padding(.trailing, 6)
+ case .bundle:
+ Image("News Bundle")
+ .resizable()
+ .frame(width: 16, height: 16, alignment: .center)
+ .padding(.trailing, 6)
+ case .article:
+ EmptyView()
+ }
+
+ Text(news.name)
+ .fontWeight((news.type == .bundle || news.type == .category || !news.read) ? .semibold : .regular)
+ .lineLimit(1)
+ .truncationMode(.tail)
+
+ if news.type == .article && news.articleUsername != nil {
+ Text(news.articleUsername!)
+ .foregroundStyle(.secondary)
+ .lineLimit(1)
+ .padding(.leading, 8)
+ }
+
+ Spacer()
+
+ if news.type == .bundle || news.type == .category {
+ ZStack {
+// Text("^[\(news.count) \(news.type == .bundle ? "Category" : "Post")](inflect: true)")
+ Text("\(news.count)")
+ .foregroundStyle(.clear)
+// .font(.caption)
+ .lineLimit(1)
+ .padding([.leading, .trailing], 8)
+ .padding([.top, .bottom], 2)
+ .background(.secondary)
+ .clipShape(Capsule())
+
+ Text("\(news.count)")
+ .foregroundStyle(.white)
+// .font(.caption)
+ .lineLimit(1)
+ .padding([.leading, .trailing], 8)
+ .padding([.top, .bottom], 2)
+ .blendMode(.destinationOut)
+ }
+ .drawingGroup(opaque: false)
+ }
+ if news.type == .article && news.articleUsername != nil {
+ if let d = news.articleDate {
+ Text(NewsItemView.relativeDateFormatter.localizedString(for: d, relativeTo: Date.now))
+ .lineLimit(1)
+ .foregroundStyle(.secondary)
+ .padding(.trailing, 8)
+ }
+ }
+ }
+ .frame(maxWidth: .infinity, maxHeight: .infinity)
+ .onChange(of: news.expanded) {
+ guard news.expanded, news.type == .bundle || news.type == .category else {
+ return
+ }
+
+ Task {
+ await model.getNewsList(at: news.path)
+ }
+ }
+
+ if news.expanded {
+ ForEach(news.children.reversed(), id: \.self) { childNews in
+ NewsItemView(news: childNews, depth: self.depth + 1).tag(childNews.id)
+ }
+ }
+ }
+}
+
+#Preview {
+ NewsItemView(news: NewsInfo(hotlineNewsArticle: HotlineNewsArticle(id: 0, parentID: 0, flags: 0, title: "Title", username: "username", date: Date.now, flavors: [("", 1)], path: ["Guest"])), depth: 0)
+ .environment(Hotline(trackerClient: HotlineTrackerClient(), client: HotlineClient()))
+}
diff --git a/Hotline/macOS/NewsView.swift b/Hotline/macOS/NewsView.swift
index f440cb2..8df741f 100644
--- a/Hotline/macOS/NewsView.swift
+++ b/Hotline/macOS/NewsView.swift
@@ -244,120 +244,6 @@ struct NewsView: View {
}
}
-struct NewsItemView: View {
- @Environment(Hotline.self) private var model: Hotline
-
- var news: NewsInfo
- let depth: Int
-
- static var dateFormatter: DateFormatter = {
- var dateFormatter = DateFormatter()
- dateFormatter.dateStyle = .long
- dateFormatter.timeStyle = .short
- dateFormatter.timeZone = .gmt
- return dateFormatter
- }()
-
- static var relativeDateFormatter: RelativeDateTimeFormatter = {
- var formatter = RelativeDateTimeFormatter()
- formatter.unitsStyle = .full
- formatter.dateTimeStyle = .named
- formatter.formattingContext = .listItem
- return formatter
- }()
-
- var body: some View {
- HStack(alignment: .center, spacing: 6) {
- if news.expandable {
- Button {
- news.expanded.toggle()
- } label: {
- Text(Image(systemName: news.expanded ? "chevron.down" : "chevron.right"))
- .bold()
- .font(.system(size: 10))
- .opacity(0.5)
- .frame(alignment: .center)
- }
- .buttonStyle(.plain)
- .frame(width: 10)
- .padding(.leading, 4)
- }
- else {
- Spacer()
- .frame(width: 14)
- }
-
- // Tree indent
- Spacer()
- .frame(width: (CGFloat(depth) * 22))
-
- switch news.type {
- case .category:
- Image("News Category")
- .resizable()
- .frame(width: 16, height: 16)
- case .bundle:
- Image("News Bundle")
- .resizable()
- .frame(width: 16, height: 16)
- case .article:
- EmptyView()
- }
-
- Text(news.name)
- .fontWeight((news.type == .bundle || news.type == .category || !news.read) ? .semibold : .regular)
- .lineLimit(1)
- .truncationMode(.tail)
- if news.type == .article && news.articleUsername != nil {
- Text(news.articleUsername!).foregroundStyle(.secondary).lineLimit(1)
- }
- Spacer()
- if news.type == .bundle || news.type == .category {
- ZStack {
- Text("^[\(news.count) \(news.type == .bundle ? "Category" : "Post")](inflect: true)")
- .foregroundStyle(.clear)
- .font(.caption2)
- .lineLimit(1)
- .padding([.leading, .trailing], 8)
- .padding([.top, .bottom], 2)
- .background(.tertiary)
- .clipShape(Capsule())
-
- Text("^[\(news.count) \(news.type == .bundle ? "Category" : "Post")](inflect: true)")
- .foregroundStyle(.white)
- .font(.caption2)
- .lineLimit(1)
- .padding([.leading, .trailing], 8)
- .padding([.top, .bottom], 2)
- .blendMode(.destinationOut)
- }
- .drawingGroup(opaque: false)
- }
- if news.type == .article && news.articleUsername != nil {
- if let d = news.articleDate {
- Text(NewsItemView.relativeDateFormatter.localizedString(for: d, relativeTo: Date.now)).lineLimit(1).foregroundStyle(.secondary)
- }
- }
- }
- .frame(maxWidth: .infinity, maxHeight: .infinity)
- .onChange(of: news.expanded) {
- guard news.expanded, news.type == .bundle || news.type == .category else {
- return
- }
-
- Task {
- await model.getNewsList(at: news.path)
- }
- }
-
- if news.expanded {
- ForEach(news.children.reversed(), id: \.self) { childNews in
- NewsItemView(news: childNews, depth: self.depth + 1).tag(childNews.id)
- }
- }
- }
-}
-
#Preview {
NewsView()
.environment(Hotline(trackerClient: HotlineTrackerClient(), client: HotlineClient()))
diff --git a/Hotline/macOS/ServerView.swift b/Hotline/macOS/ServerView.swift
index 21d7cbb..9b4c044 100644
--- a/Hotline/macOS/ServerView.swift
+++ b/Hotline/macOS/ServerView.swift
@@ -146,10 +146,10 @@ struct ServerView: View {
@Binding var server: Server
static var menuItems: [ServerMenuItem] = [
- ServerMenuItem(type: .chat, name: "Chat", image: "bubble.fill"),
- ServerMenuItem(type: .board, name: "Board", image: "pin.fill"),
- ServerMenuItem(type: .news, name: "News", image: "newspaper.fill"),
- ServerMenuItem(type: .files, name: "Files", image: "folder.fill"),
+ ServerMenuItem(type: .chat, name: "Chat", image: "bubble"),
+ ServerMenuItem(type: .board, name: "Board", image: "pin"),
+ ServerMenuItem(type: .news, name: "News", image: "newspaper"),
+ ServerMenuItem(type: .files, name: "Files", image: "folder"),
]
enum FocusFields {
@@ -197,12 +197,12 @@ struct ServerView: View {
.onChange(of: Prefs.shared.automaticMessage) { sendPreferences() }
.toolbar {
ToolbarItem(placement: .navigation) {
- Image(systemName: "globe.americas.fill")
- .renderingMode(.template)
+ Image("Server Large")
+// .renderingMode(.template)
.resizable()
.scaledToFit()
- .frame(width: 18)
+ .frame(width: 24)
.opacity(controlActiveState == .inactive ? 0.4 : 1.0)
}
}
diff --git a/Hotline/macOS/TrackerView.swift b/Hotline/macOS/TrackerView.swift
index a07d40c..f9755f8 100644
--- a/Hotline/macOS/TrackerView.swift
+++ b/Hotline/macOS/TrackerView.swift
@@ -311,17 +311,28 @@ struct TrackerItemView: View {
.padding(.leading, 4)
}
- HStack(alignment: .center) {
+ HStack(alignment: .center, spacing: 0) {
if let bookmark = item.bookmark {
switch bookmark.type {
case .tracker:
- Image(systemName: "point.3.filled.connected.trianglepath.dotted")
+// Image(systemName: "point.3.filled.connected.trianglepath.dotted")
+ Image("Tracker")
+ .resizable()
+ .scaledToFit()
+ .frame(width: 16, height: 16)
case .server:
- Image(systemName: "globe.americas.fill")
+ Image("Server")
+ .resizable()
+ .scaledToFit()
+ .frame(width: 16, height: 16)
+// Image(systemName: "globe.americas.fill")
}
}
else if let _ = item.server {
- Image(systemName: "globe.americas.fill")
+ Image("Server")
+ .resizable()
+ .scaledToFit()
+ .frame(width: 16, height: 16)
}
}
.frame(width: 15)