diff options
| author | Dustin Mierau <dustin@mierau.me> | 2025-10-27 21:48:20 -0700 |
|---|---|---|
| committer | Dustin Mierau <dustin@mierau.me> | 2025-10-27 21:48:20 -0700 |
| commit | 4bb0ffba596e41a8309ba50d222248a0ba3eb42e (patch) | |
| tree | fcd1c2b11c071a624d0b3b56ed16340272200c7d /Hotline/macOS/News/NewsItemView.swift | |
| parent | 924012e6ee03fff5570e9362e29be9b04816b777 (diff) | |
Random project housekeeping/organizing source files.
Diffstat (limited to 'Hotline/macOS/News/NewsItemView.swift')
| -rw-r--r-- | Hotline/macOS/News/NewsItemView.swift | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/Hotline/macOS/News/NewsItemView.swift b/Hotline/macOS/News/NewsItemView.swift new file mode 100644 index 0000000..fc20e61 --- /dev/null +++ b/Hotline/macOS/News/NewsItemView.swift @@ -0,0 +1,152 @@ +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 == .category && news.count > 0 { + Text("^[\(news.count) Post](inflect: true)") + .lineLimit(1) + .foregroundStyle(.secondary) + .padding(.trailing, 8) + } + else if news.type == .bundle && news.count > 0 { + Text("^[\(news.count) Category](inflect: true)") + .lineLimit(1) + .foregroundStyle(.secondary) + .padding(.trailing, 8) + } +// if news.type == .bundle { +// Text("\(news.count)") +// .lineLimit(1) +// .foregroundStyle(.tertiary) +// .padding(.trailing, 8) + +// 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) +// } + else 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())) +} |