diff options
| author | Ruben Beltran del Rio <git@r.bdr.sh> | 2025-11-27 23:38:04 +0100 |
|---|---|---|
| committer | Ruben Beltran del Rio <git@r.bdr.sh> | 2025-11-27 23:38:04 +0100 |
| commit | 213710bf5bd6413c747bf126db50816ef5de5a6e (patch) | |
| tree | 912f8cf87955a08077c92fea8ad934f50b7ab975 /Hotline/macOS/News/NewsItemView.swift | |
| parent | f466b21dc02f78c984ba6748e703f6780a7a0db4 (diff) | |
| parent | 6a95b53616a4abfa306ddce43151cf4fefbd20ed (diff) | |
Merge remote-tracking branch 'upstream/main'
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..d477348 --- /dev/null +++ b/Hotline/macOS/News/NewsItemView.swift @@ -0,0 +1,152 @@ +import SwiftUI + +struct NewsItemView: View { + @Environment(HotlineState.self) private var model: HotlineState + + 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 { + try? 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(HotlineState()) +} |