diff options
Diffstat (limited to 'Hotline')
23 files changed, 254 insertions, 140 deletions
diff --git a/Hotline/Assets.xcassets/News Bundle.imageset/News Bundle.png b/Hotline/Assets.xcassets/News Bundle.imageset/News Bundle.png Binary files differindex ea6fe08..b0f4ee4 100644 --- a/Hotline/Assets.xcassets/News Bundle.imageset/News Bundle.png +++ b/Hotline/Assets.xcassets/News Bundle.imageset/News Bundle.png diff --git a/Hotline/Assets.xcassets/News Bundle.imageset/News Bundle@2x.png b/Hotline/Assets.xcassets/News Bundle.imageset/News Bundle@2x.png Binary files differindex 8271cc3..4728426 100644 --- a/Hotline/Assets.xcassets/News Bundle.imageset/News Bundle@2x.png +++ b/Hotline/Assets.xcassets/News Bundle.imageset/News Bundle@2x.png diff --git a/Hotline/Assets.xcassets/News Bundle.imageset/News Bundle@3x.png b/Hotline/Assets.xcassets/News Bundle.imageset/News Bundle@3x.png Binary files differindex b018b6d..cc7e0a2 100644 --- a/Hotline/Assets.xcassets/News Bundle.imageset/News Bundle@3x.png +++ b/Hotline/Assets.xcassets/News Bundle.imageset/News Bundle@3x.png diff --git a/Hotline/Assets.xcassets/News Category.imageset/News Category.png b/Hotline/Assets.xcassets/News Category.imageset/News Category.png Binary files differindex cc8554b..5f58a1e 100644 --- a/Hotline/Assets.xcassets/News Category.imageset/News Category.png +++ b/Hotline/Assets.xcassets/News Category.imageset/News Category.png diff --git a/Hotline/Assets.xcassets/News Category.imageset/News Category@2x.png b/Hotline/Assets.xcassets/News Category.imageset/News Category@2x.png Binary files differindex 28053fd..d3eff96 100644 --- a/Hotline/Assets.xcassets/News Category.imageset/News Category@2x.png +++ b/Hotline/Assets.xcassets/News Category.imageset/News Category@2x.png diff --git a/Hotline/Assets.xcassets/News Category.imageset/News Category@3x.png b/Hotline/Assets.xcassets/News Category.imageset/News Category@3x.png Binary files differindex 0c968bb..371d15a 100644 --- a/Hotline/Assets.xcassets/News Category.imageset/News Category@3x.png +++ b/Hotline/Assets.xcassets/News Category.imageset/News Category@3x.png diff --git a/Hotline/Assets.xcassets/Server Large.imageset/Contents.json b/Hotline/Assets.xcassets/Server Large.imageset/Contents.json new file mode 100644 index 0000000..0c15637 --- /dev/null +++ b/Hotline/Assets.xcassets/Server Large.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "Server Large.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Server Large@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Server Large@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Hotline/Assets.xcassets/Server Large.imageset/Server Large.png b/Hotline/Assets.xcassets/Server Large.imageset/Server Large.png Binary files differnew file mode 100644 index 0000000..25a97b0 --- /dev/null +++ b/Hotline/Assets.xcassets/Server Large.imageset/Server Large.png diff --git a/Hotline/Assets.xcassets/Server Large.imageset/Server Large@2x.png b/Hotline/Assets.xcassets/Server Large.imageset/Server Large@2x.png Binary files differnew file mode 100644 index 0000000..63fe295 --- /dev/null +++ b/Hotline/Assets.xcassets/Server Large.imageset/Server Large@2x.png diff --git a/Hotline/Assets.xcassets/Server Large.imageset/Server Large@3x.png b/Hotline/Assets.xcassets/Server Large.imageset/Server Large@3x.png Binary files differnew file mode 100644 index 0000000..7b8cd6e --- /dev/null +++ b/Hotline/Assets.xcassets/Server Large.imageset/Server Large@3x.png diff --git a/Hotline/Assets.xcassets/Server.imageset/Contents.json b/Hotline/Assets.xcassets/Server.imageset/Contents.json new file mode 100644 index 0000000..0bfbf05 --- /dev/null +++ b/Hotline/Assets.xcassets/Server.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "Server.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Server@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Server@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Hotline/Assets.xcassets/Server.imageset/Server.png b/Hotline/Assets.xcassets/Server.imageset/Server.png Binary files differnew file mode 100644 index 0000000..3b63a79 --- /dev/null +++ b/Hotline/Assets.xcassets/Server.imageset/Server.png diff --git a/Hotline/Assets.xcassets/Server.imageset/Server@2x.png b/Hotline/Assets.xcassets/Server.imageset/Server@2x.png Binary files differnew file mode 100644 index 0000000..ede8ce0 --- /dev/null +++ b/Hotline/Assets.xcassets/Server.imageset/Server@2x.png diff --git a/Hotline/Assets.xcassets/Server.imageset/Server@3x.png b/Hotline/Assets.xcassets/Server.imageset/Server@3x.png Binary files differnew file mode 100644 index 0000000..eb3e466 --- /dev/null +++ b/Hotline/Assets.xcassets/Server.imageset/Server@3x.png diff --git a/Hotline/Assets.xcassets/Tracker.imageset/Contents.json b/Hotline/Assets.xcassets/Tracker.imageset/Contents.json new file mode 100644 index 0000000..7006942 --- /dev/null +++ b/Hotline/Assets.xcassets/Tracker.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "Tracker.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Tracker@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Tracker@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Hotline/Assets.xcassets/Tracker.imageset/Tracker.png b/Hotline/Assets.xcassets/Tracker.imageset/Tracker.png Binary files differnew file mode 100644 index 0000000..6fc5957 --- /dev/null +++ b/Hotline/Assets.xcassets/Tracker.imageset/Tracker.png diff --git a/Hotline/Assets.xcassets/Tracker.imageset/Tracker@2x.png b/Hotline/Assets.xcassets/Tracker.imageset/Tracker@2x.png Binary files differnew file mode 100644 index 0000000..ba3b2bb --- /dev/null +++ b/Hotline/Assets.xcassets/Tracker.imageset/Tracker@2x.png diff --git a/Hotline/Assets.xcassets/Tracker.imageset/Tracker@3x.png b/Hotline/Assets.xcassets/Tracker.imageset/Tracker@3x.png Binary files differnew file mode 100644 index 0000000..32e9056 --- /dev/null +++ b/Hotline/Assets.xcassets/Tracker.imageset/Tracker@3x.png 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) |