aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Hotline.xcodeproj/project.pbxproj6
-rw-r--r--Hotline/Assets.xcassets/Classic/176.imageset/176@2x.pngbin2278 -> 2352 bytes
-rw-r--r--Hotline/Assets.xcassets/Classic/176.imageset/176@3x.pngbin3776 -> 3918 bytes
-rw-r--r--Hotline/Assets.xcassets/Classic/2004.imageset/2004@2x.pngbin0 -> 908 bytes
-rw-r--r--Hotline/Assets.xcassets/Classic/2004.imageset/2004@3x.pngbin0 -> 1519 bytes
-rw-r--r--Hotline/Assets.xcassets/Classic/2004.imageset/Contents.json2
-rw-r--r--Hotline/Assets.xcassets/News Bundle.imageset/Contents.json23
-rw-r--r--Hotline/Assets.xcassets/News Bundle.imageset/Frame 3.pngbin0 -> 405 bytes
-rw-r--r--Hotline/Assets.xcassets/News Bundle.imageset/Frame 3@2x.pngbin0 -> 988 bytes
-rw-r--r--Hotline/Assets.xcassets/News Bundle.imageset/Frame 3@3x.pngbin0 -> 1783 bytes
-rw-r--r--Hotline/Assets.xcassets/News Category.imageset/Contents.json23
-rw-r--r--Hotline/Assets.xcassets/News Category.imageset/Frame 1.pngbin0 -> 402 bytes
-rw-r--r--Hotline/Assets.xcassets/News Category.imageset/Frame 1@2x.pngbin0 -> 777 bytes
-rw-r--r--Hotline/Assets.xcassets/News Category.imageset/Frame 1@3x.pngbin0 -> 1178 bytes
-rw-r--r--Hotline/Models/Hotline.swift36
-rw-r--r--Hotline/Models/NewsInfo.swift1
-rw-r--r--Hotline/macOS/NewsView.swift53
17 files changed, 117 insertions, 27 deletions
diff --git a/Hotline.xcodeproj/project.pbxproj b/Hotline.xcodeproj/project.pbxproj
index 32eadbf..22e9ce0 100644
--- a/Hotline.xcodeproj/project.pbxproj
+++ b/Hotline.xcodeproj/project.pbxproj
@@ -289,14 +289,14 @@
DADDB2892B22B2C60024040D /* Models */ = {
isa = PBXGroup;
children = (
- 11A726072BE0672A000C1DA7 /* FileDetails.swift */,
+ DADDB28E2B238D850024040D /* Hotline.swift */,
DADDB28A2B22B31F0024040D /* Tracker.swift */,
DAC3D9822BC33FD000A727C9 /* ApplicationState.swift */,
DABE8C052B57A06100884D28 /* Bookmarks.swift */,
DA2863D92B37BF6E00A7D050 /* Preferences.swift */,
- DADDB28E2B238D850024040D /* Hotline.swift */,
DADDB28C2B22B5920024040D /* Server.swift */,
DA32CD482B2931640053B98B /* User.swift */,
+ 11A726072BE0672A000C1DA7 /* FileDetails.swift */,
DA32CD4A2B29318E0053B98B /* FileInfo.swift */,
DAAEE66A2B3FBC2100A5BA07 /* TransferInfo.swift */,
DA2863DC2B3E8B7000A7D050 /* FilePreview.swift */,
@@ -316,13 +316,13 @@
DAE734F82B2E4185000C56F6 /* ServerView.swift */,
DAE734FE2B2E6750000C56F6 /* ChatView.swift */,
DAE735042B3218D8000C56F6 /* NewsView.swift */,
+ DA72A0DC2B4CD0BF00A0F48A /* NewsEditorView.swift */,
DAE735022B30C0BB000C56F6 /* MessageView.swift */,
DAE734FC2B2E65E9000C56F6 /* MessageBoardView.swift */,
DAE735002B2E71F2000C56F6 /* FilesView.swift */,
DAAEE66E2B47625600A5BA07 /* FilePreviewImageView.swift */,
DAB4D87D2B4C8BCA0048A05C /* FilePreviewTextView.swift */,
11A726092BE06759000C1DA7 /* FileDetailsView.swift */,
- DA72A0DC2B4CD0BF00A0F48A /* NewsEditorView.swift */,
DA2863D72B37AD1C00A7D050 /* SettingsView.swift */,
DAE136B92B9D1147007D8307 /* HotlinePanelView.swift */,
DA55AC762BE589F700034857 /* AboutView.swift */,
diff --git a/Hotline/Assets.xcassets/Classic/176.imageset/176@2x.png b/Hotline/Assets.xcassets/Classic/176.imageset/176@2x.png
index 929e7f0..983812e 100644
--- a/Hotline/Assets.xcassets/Classic/176.imageset/176@2x.png
+++ b/Hotline/Assets.xcassets/Classic/176.imageset/176@2x.png
Binary files differ
diff --git a/Hotline/Assets.xcassets/Classic/176.imageset/176@3x.png b/Hotline/Assets.xcassets/Classic/176.imageset/176@3x.png
index ae03a1d..a485383 100644
--- a/Hotline/Assets.xcassets/Classic/176.imageset/176@3x.png
+++ b/Hotline/Assets.xcassets/Classic/176.imageset/176@3x.png
Binary files differ
diff --git a/Hotline/Assets.xcassets/Classic/2004.imageset/2004@2x.png b/Hotline/Assets.xcassets/Classic/2004.imageset/2004@2x.png
new file mode 100644
index 0000000..8466dc7
--- /dev/null
+++ b/Hotline/Assets.xcassets/Classic/2004.imageset/2004@2x.png
Binary files differ
diff --git a/Hotline/Assets.xcassets/Classic/2004.imageset/2004@3x.png b/Hotline/Assets.xcassets/Classic/2004.imageset/2004@3x.png
new file mode 100644
index 0000000..4dedd55
--- /dev/null
+++ b/Hotline/Assets.xcassets/Classic/2004.imageset/2004@3x.png
Binary files differ
diff --git a/Hotline/Assets.xcassets/Classic/2004.imageset/Contents.json b/Hotline/Assets.xcassets/Classic/2004.imageset/Contents.json
index 188024d..43cde06 100644
--- a/Hotline/Assets.xcassets/Classic/2004.imageset/Contents.json
+++ b/Hotline/Assets.xcassets/Classic/2004.imageset/Contents.json
@@ -6,10 +6,12 @@
"scale" : "1x"
},
{
+ "filename" : "2004@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
+ "filename" : "2004@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
diff --git a/Hotline/Assets.xcassets/News Bundle.imageset/Contents.json b/Hotline/Assets.xcassets/News Bundle.imageset/Contents.json
new file mode 100644
index 0000000..bfb6d35
--- /dev/null
+++ b/Hotline/Assets.xcassets/News Bundle.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+ "images" : [
+ {
+ "filename" : "Frame 3.png",
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "filename" : "Frame 3@2x.png",
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "filename" : "Frame 3@3x.png",
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/Hotline/Assets.xcassets/News Bundle.imageset/Frame 3.png b/Hotline/Assets.xcassets/News Bundle.imageset/Frame 3.png
new file mode 100644
index 0000000..46d144d
--- /dev/null
+++ b/Hotline/Assets.xcassets/News Bundle.imageset/Frame 3.png
Binary files differ
diff --git a/Hotline/Assets.xcassets/News Bundle.imageset/Frame 3@2x.png b/Hotline/Assets.xcassets/News Bundle.imageset/Frame 3@2x.png
new file mode 100644
index 0000000..2dbb989
--- /dev/null
+++ b/Hotline/Assets.xcassets/News Bundle.imageset/Frame 3@2x.png
Binary files differ
diff --git a/Hotline/Assets.xcassets/News Bundle.imageset/Frame 3@3x.png b/Hotline/Assets.xcassets/News Bundle.imageset/Frame 3@3x.png
new file mode 100644
index 0000000..649ab86
--- /dev/null
+++ b/Hotline/Assets.xcassets/News Bundle.imageset/Frame 3@3x.png
Binary files differ
diff --git a/Hotline/Assets.xcassets/News Category.imageset/Contents.json b/Hotline/Assets.xcassets/News Category.imageset/Contents.json
new file mode 100644
index 0000000..7245ec5
--- /dev/null
+++ b/Hotline/Assets.xcassets/News Category.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+ "images" : [
+ {
+ "filename" : "Frame 1.png",
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "filename" : "Frame 1@2x.png",
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "filename" : "Frame 1@3x.png",
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/Hotline/Assets.xcassets/News Category.imageset/Frame 1.png b/Hotline/Assets.xcassets/News Category.imageset/Frame 1.png
new file mode 100644
index 0000000..1c3a080
--- /dev/null
+++ b/Hotline/Assets.xcassets/News Category.imageset/Frame 1.png
Binary files differ
diff --git a/Hotline/Assets.xcassets/News Category.imageset/Frame 1@2x.png b/Hotline/Assets.xcassets/News Category.imageset/Frame 1@2x.png
new file mode 100644
index 0000000..e1bce20
--- /dev/null
+++ b/Hotline/Assets.xcassets/News Category.imageset/Frame 1@2x.png
Binary files differ
diff --git a/Hotline/Assets.xcassets/News Category.imageset/Frame 1@3x.png b/Hotline/Assets.xcassets/News Category.imageset/Frame 1@3x.png
new file mode 100644
index 0000000..6a16cef
--- /dev/null
+++ b/Hotline/Assets.xcassets/News Category.imageset/Frame 1@3x.png
Binary files differ
diff --git a/Hotline/Models/Hotline.swift b/Hotline/Models/Hotline.swift
index 598c787..48266a9 100644
--- a/Hotline/Models/Hotline.swift
+++ b/Hotline/Models/Hotline.swift
@@ -345,30 +345,58 @@ class Hotline: Equatable, HotlineClientDelegate, HotlineFileClientDelegate {
self?.client.sendGetNewsArticles(path: path) { [weak self] articles in
// let parentNews = self?.findNews(in: self?.news ?? [], at: path)
print("GENERATING NEWS")
-
+
var newArticles: [NewsInfo] = []
for article in articles {
newArticles.append(NewsInfo(hotlineNewsArticle: article))
}
+ let organizedNewsArticles: [NewsInfo] = self?.organizeNewsList(newArticles) ?? []
+
DispatchQueue.main.async {
if let parent = existingNewsItem {
print("UNDER PARENT:", parent.name)
- parent.children = newArticles
+ parent.children = organizedNewsArticles
print(parent.children)
}
else if path.isEmpty {
- self?.news = newArticles
+ self?.news = organizedNewsArticles
}
- continuation.resume(returning: newArticles)
+ continuation.resume(returning: organizedNewsArticles)
}
}
}
}
}
+ func organizeNewsList(_ news: [NewsInfo]) -> [NewsInfo] {
+ var articleMap: [UInt: NewsInfo] = [:]
+
+ // Create lookup table of each news item.
+ for article in news {
+ if let articleID = article.articleID {
+ articleMap[articleID] = article
+ }
+ }
+
+ // Place articles under their parent.
+ var organized: [NewsInfo] = []
+ for article in news {
+ if let parentID = article.parentID,
+ parentID != 0,
+ let parentArticle = articleMap[parentID] {
+ parentArticle.children.append(article)
+ }
+ else {
+ organized.append(article)
+ }
+ }
+
+ return organized
+ }
+
@MainActor func getNewsCategories(at path: [String] = []) async -> [NewsInfo] {
return await withCheckedContinuation { [weak self] continuation in
self?.client.sendGetNewsCategories(path: path) { [weak self] categories in
diff --git a/Hotline/Models/NewsInfo.swift b/Hotline/Models/NewsInfo.swift
index f95cba1..b635138 100644
--- a/Hotline/Models/NewsInfo.swift
+++ b/Hotline/Models/NewsInfo.swift
@@ -24,6 +24,7 @@ enum NewsInfoType {
var articleFlavors: [String]?
var articleUsername: String?
var articleDate: Date?
+ var read: Bool = false
init(hotlineNewsCategory: HotlineNewsCategory) {
self.categoryID = hotlineNewsCategory.id
diff --git a/Hotline/macOS/NewsView.swift b/Hotline/macOS/NewsView.swift
index 875765e..e87a7f0 100644
--- a/Hotline/macOS/NewsView.swift
+++ b/Hotline/macOS/NewsView.swift
@@ -119,13 +119,14 @@ struct NewsView: View {
}
self.selection = clickedNews
- if clickedNews.type == .bundle || clickedNews.type == .category {
+ if clickedNews.type == .bundle || clickedNews.type == .category || clickedNews.children.count > 0 {
clickedNews.expanded.toggle()
}
}
.onChange(of: selection) {
self.articleText = nil
if let article = selection, article.type == .article {
+ article.read = true
if let articleFlavor = article.articleFlavors?.first,
let articleID = article.articleID {
Task {
@@ -247,7 +248,7 @@ struct NewsItemView: View {
var body: some View {
HStack(alignment: .center, spacing: 6) {
- if news.type == .bundle || news.type == .category {
+ if news.type == .bundle || news.type == .category || news.children.count > 0 {
Button {
news.expanded.toggle()
} label: {
@@ -261,19 +262,31 @@ struct NewsItemView: View {
.frame(width: 10)
.padding(.leading, 4)
}
- else if news.type == .article {
- if news.parentID != nil {
- Image(systemName: "arrowshape.turn.up.left.fill")
- .resizable()
- .renderingMode(.template)
- .scaledToFit()
- .frame(width: 10)
- .foregroundStyle(.secondary)
- .opacity(0.5)
- }
+ else {
+ Spacer()
+ .frame(width: 14)
}
+
+ // Tree indent
+ Spacer()
+ .frame(width: CGFloat(max(0, depth-1)) * 16)
+
+ 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:
+ Spacer()
+ .frame(width: 16)
+ }
+
Text(news.name)
- .fontWeight((news.type == .bundle || news.type == .category) ? .bold : .regular)
+ .fontWeight((news.type == .bundle || news.type == .category || !news.read) ? .semibold : .regular)
.lineLimit(1)
.truncationMode(.tail)
if news.type == .article && news.articleUsername != nil {
@@ -282,8 +295,6 @@ struct NewsItemView: View {
Spacer()
if news.type == .bundle || news.type == .category {
Text("^[\(news.count) \(news.type == .bundle ? "Category" : "Post")](inflect: true)")
-
-// Text("\(news.count) \(news.type == .bundle ? "Categories" : "Posts")")
.foregroundStyle(.secondary)
.lineLimit(1)
.padding([.leading, .trailing], 8)
@@ -297,13 +308,15 @@ struct NewsItemView: View {
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
- .padding(.leading, CGFloat(depth * (12 + 10)))
.onChange(of: news.expanded) {
+ guard news.expanded else {
+ return
+ }
+
+ news.read = true
if news.type == .bundle || news.type == .category {
- if news.expanded {
- Task {
- await model.getNewsList(at: news.path)
- }
+ Task {
+ await model.getNewsList(at: news.path)
}
}
}