aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Hotline.xcodeproj/project.pbxproj8
-rw-r--r--Hotline/Assets.xcassets/Message Board Post.imageset/Contents.json23
-rw-r--r--Hotline/Assets.xcassets/Message Board Post.imageset/Message Board Post.pngbin0 -> 392 bytes
-rw-r--r--Hotline/Assets.xcassets/Message Board Post.imageset/Message Board Post@2x.pngbin0 -> 701 bytes
-rw-r--r--Hotline/Assets.xcassets/Message Board Post.imageset/Message Board Post@3x.pngbin0 -> 1002 bytes
-rw-r--r--Hotline/Models/Hotline.swift4
-rw-r--r--Hotline/Shared/TextView.swift119
-rw-r--r--Hotline/Utility/FoundationExtensions.swift22
-rw-r--r--Hotline/macOS/MessageBoardEditorView.swift117
-rw-r--r--Hotline/macOS/MessageBoardView.swift58
-rw-r--r--Hotline/macOS/NewsEditorView.swift18
-rw-r--r--Hotline/macOS/NewsView.swift2
-rw-r--r--Hotline/macOS/ServerView.swift9
13 files changed, 340 insertions, 40 deletions
diff --git a/Hotline.xcodeproj/project.pbxproj b/Hotline.xcodeproj/project.pbxproj
index 858cc6c..75578a4 100644
--- a/Hotline.xcodeproj/project.pbxproj
+++ b/Hotline.xcodeproj/project.pbxproj
@@ -35,6 +35,8 @@
DA65499A2BEC280E00EDB697 /* ServerMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA6549992BEC280E00EDB697 /* ServerMessageView.swift */; };
DA65499C2BEC3FBD00EDB697 /* ServerAgreementView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA65499B2BEC3FBD00EDB697 /* ServerAgreementView.swift */; };
DA65499E2BEC438A00EDB697 /* NSWindowBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA65499D2BEC438A00EDB697 /* NSWindowBridge.swift */; };
+ DA6980792BF80525003E434B /* TextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA6980782BF80525003E434B /* TextView.swift */; };
+ DA69807E2BFD449B003E434B /* MessageBoardEditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA69807D2BFD449B003E434B /* MessageBoardEditorView.swift */; };
DA72A0DD2B4CD0BF00A0F48A /* NewsEditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA72A0DC2B4CD0BF00A0F48A /* NewsEditorView.swift */; };
DA72A0E02B4DA8CA00A0F48A /* SplitView in Frameworks */ = {isa = PBXBuildFile; productRef = DA72A0DF2B4DA8CA00A0F48A /* SplitView */; };
DA72A0E22B4DAA4000A0F48A /* NewsArticle.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA72A0E12B4DAA4000A0F48A /* NewsArticle.swift */; };
@@ -114,6 +116,8 @@
DA6549992BEC280E00EDB697 /* ServerMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerMessageView.swift; sourceTree = "<group>"; };
DA65499B2BEC3FBD00EDB697 /* ServerAgreementView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerAgreementView.swift; sourceTree = "<group>"; };
DA65499D2BEC438A00EDB697 /* NSWindowBridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSWindowBridge.swift; sourceTree = "<group>"; };
+ DA6980782BF80525003E434B /* TextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextView.swift; sourceTree = "<group>"; };
+ DA69807D2BFD449B003E434B /* MessageBoardEditorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageBoardEditorView.swift; sourceTree = "<group>"; };
DA72A0DC2B4CD0BF00A0F48A /* NewsEditorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewsEditorView.swift; sourceTree = "<group>"; };
DA72A0E12B4DAA4000A0F48A /* NewsArticle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewsArticle.swift; sourceTree = "<group>"; };
DA77253E2B21176D006C5ABB /* NewsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewsView.swift; sourceTree = "<group>"; };
@@ -243,6 +247,7 @@
DA872B122BDDBF78008B1012 /* HotlinePanel.swift */,
DA872B142BDDEE1A008B1012 /* VisualEffectView.swift */,
DA55AC722BE42AF000034857 /* AsyncLinkPreview.swift */,
+ DA6980782BF80525003E434B /* TextView.swift */,
);
path = Shared;
sourceTree = "<group>";
@@ -322,6 +327,7 @@
DA72A0DC2B4CD0BF00A0F48A /* NewsEditorView.swift */,
DAE735022B30C0BB000C56F6 /* MessageView.swift */,
DAE734FC2B2E65E9000C56F6 /* MessageBoardView.swift */,
+ DA69807D2BFD449B003E434B /* MessageBoardEditorView.swift */,
DAE735002B2E71F2000C56F6 /* FilesView.swift */,
DAAEE66E2B47625600A5BA07 /* FilePreviewImageView.swift */,
DAB4D87D2B4C8BCA0048A05C /* FilePreviewTextView.swift */,
@@ -445,6 +451,7 @@
11A726082BE0672A000C1DA7 /* FileDetails.swift in Sources */,
DA9CAFBD2B126D5700CDA197 /* TrackerView.swift in Sources */,
DAB4D87B2B4B78310048A05C /* FileImageView.swift in Sources */,
+ DA6980792BF80525003E434B /* TextView.swift in Sources */,
DA55AC732BE42AF000034857 /* AsyncLinkPreview.swift in Sources */,
DA65499E2BEC438A00EDB697 /* NSWindowBridge.swift in Sources */,
DAE735032B30C0BB000C56F6 /* MessageView.swift in Sources */,
@@ -458,6 +465,7 @@
DA0D698F2B1E841600C71DF5 /* MessageBoardView.swift in Sources */,
DAE735072B3251B3000C56F6 /* SoundEffects.swift in Sources */,
DA55AC752BE4888300034857 /* InstantMessage.swift in Sources */,
+ DA69807E2BFD449B003E434B /* MessageBoardEditorView.swift in Sources */,
DAE735012B2E71F2000C56F6 /* FilesView.swift in Sources */,
DA55AC792BE6A1AD00034857 /* RegularExpressions.swift in Sources */,
11A7260A2BE0675A000C1DA7 /* FileDetailsView.swift in Sources */,
diff --git a/Hotline/Assets.xcassets/Message Board Post.imageset/Contents.json b/Hotline/Assets.xcassets/Message Board Post.imageset/Contents.json
new file mode 100644
index 0000000..8147f45
--- /dev/null
+++ b/Hotline/Assets.xcassets/Message Board Post.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+ "images" : [
+ {
+ "filename" : "Message Board Post.png",
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "filename" : "Message Board Post@2x.png",
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "filename" : "Message Board Post@3x.png",
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/Hotline/Assets.xcassets/Message Board Post.imageset/Message Board Post.png b/Hotline/Assets.xcassets/Message Board Post.imageset/Message Board Post.png
new file mode 100644
index 0000000..80f0f73
--- /dev/null
+++ b/Hotline/Assets.xcassets/Message Board Post.imageset/Message Board Post.png
Binary files differ
diff --git a/Hotline/Assets.xcassets/Message Board Post.imageset/Message Board Post@2x.png b/Hotline/Assets.xcassets/Message Board Post.imageset/Message Board Post@2x.png
new file mode 100644
index 0000000..990e5fd
--- /dev/null
+++ b/Hotline/Assets.xcassets/Message Board Post.imageset/Message Board Post@2x.png
Binary files differ
diff --git a/Hotline/Assets.xcassets/Message Board Post.imageset/Message Board Post@3x.png b/Hotline/Assets.xcassets/Message Board Post.imageset/Message Board Post@3x.png
new file mode 100644
index 0000000..6f293b5
--- /dev/null
+++ b/Hotline/Assets.xcassets/Message Board Post.imageset/Message Board Post@3x.png
Binary files differ
diff --git a/Hotline/Models/Hotline.swift b/Hotline/Models/Hotline.swift
index ce917cd..93f1762 100644
--- a/Hotline/Models/Hotline.swift
+++ b/Hotline/Models/Hotline.swift
@@ -259,7 +259,7 @@ class Hotline: Equatable, HotlineClientDelegate, HotlineFileClientDelegate {
@MainActor func postToMessageBoard(text: String) {
self.client.sendPostMessageBoard(text: text)
}
-
+
@MainActor func getFileList(path: [String] = []) async -> [FileInfo] {
return await withCheckedContinuation { [weak self] continuation in
self?.client.sendGetFileList(path: path) { [weak self] files in
@@ -422,6 +422,8 @@ class Hotline: Equatable, HotlineClientDelegate, HotlineFileClientDelegate {
}
@MainActor func postNewsArticle(title: String, body: String, at path: [String], parentID: UInt32 = 0) async -> Bool {
+
+
return await withCheckedContinuation { [weak self] continuation in
guard let client = self?.client else {
continuation.resume(returning: false)
diff --git a/Hotline/Shared/TextView.swift b/Hotline/Shared/TextView.swift
new file mode 100644
index 0000000..47746e2
--- /dev/null
+++ b/Hotline/Shared/TextView.swift
@@ -0,0 +1,119 @@
+import SwiftUI
+
+struct BetterTextEditor: NSViewRepresentable {
+
+ @Environment(\.lineSpacing) private var lineSpacing
+
+ @Binding private var text: String
+
+ private var customizations: [(NSTextView) -> Void] = []
+
+ init(text: Binding<String>) {
+ self._text = text
+ }
+
+ func makeCoordinator() -> Coordinator {
+ Coordinator(self)
+ }
+
+ func makeNSView(context: Context) -> NSScrollView {
+ let scrollview = NSTextView.scrollablePlainDocumentContentTextView()
+ let textview = scrollview.documentView as! NSTextView
+
+ textview.string = self.text
+ textview.delegate = context.coordinator
+
+// let p = NSMutableParagraphStyle()
+// p.lineSpacing = self.lineSpacing
+//// textview.defaultParagraphStyle = p
+// textview.typingAttributes = [
+// .paragraphStyle: p
+// ]
+
+ textview.isEditable = true
+ textview.isRichText = false
+ textview.allowsUndo = true
+ textview.isFieldEditor = false
+ textview.usesAdaptiveColorMappingForDarkAppearance = true
+ textview.drawsBackground = false // true
+ textview.usesRuler = false
+ textview.usesFindBar = false
+ textview.isIncrementalSearchingEnabled = false
+ textview.isAutomaticQuoteSubstitutionEnabled = false
+ textview.isAutomaticDashSubstitutionEnabled = false
+ textview.isAutomaticSpellingCorrectionEnabled = true
+ textview.isAutomaticDataDetectionEnabled = false
+ textview.isAutomaticLinkDetectionEnabled = false
+ textview.usesInspectorBar = false
+ textview.usesFontPanel = false
+ textview.importsGraphics = false
+ textview.allowsImageEditing = false
+ textview.displaysLinkToolTips = true
+ textview.backgroundColor = NSColor.textBackgroundColor
+ textview.textContainerInset = NSSize(width: 16, height: 16)
+ textview.isContinuousSpellCheckingEnabled = true
+ textview.setSelectedRange(NSMakeRange(0, 0))
+ self.customizations.forEach { $0(textview) }
+
+ scrollview.scrollerStyle = .overlay
+
+ return scrollview
+ }
+
+ func updateNSView(_ nsView: NSScrollView, context: Context) {
+ let textview = nsView.documentView as! NSTextView
+
+ if textview.string != text {
+ textview.string = text
+ }
+
+ self.customizations.forEach { $0(textview) }
+ }
+
+ func betterEditorFont(_ font: NSFont) -> Self {
+ self.customized { $0.font = font }
+ }
+
+ func betterEditorParagraphStyle(_ paragraphStyle: NSParagraphStyle) -> Self {
+ self.customized { $0.defaultParagraphStyle = paragraphStyle }
+ }
+
+ func betterEditorAutomaticDashSubstitution(_ enabled: Bool) -> Self {
+ self.customized { $0.isAutomaticDashSubstitutionEnabled = enabled }
+ }
+
+ func betterEditorAutomaticQuoteSubstitution(_ enabled: Bool) -> Self {
+ self.customized { $0.isAutomaticQuoteSubstitutionEnabled = enabled }
+ }
+
+ func betterEditorAutomaticSpellingCorrection(_ enabled: Bool) -> Self {
+ self.customized { $0.isAutomaticSpellingCorrectionEnabled = enabled }
+ }
+
+ func betterEditorTextInset(_ size: NSSize) -> Self {
+ self.customized { $0.textContainerInset = size }
+ }
+
+ class Coordinator: NSObject, NSTextViewDelegate {
+ var parent: BetterTextEditor
+
+ init(_ parent: BetterTextEditor) {
+ self.parent = parent
+ }
+
+ func textDidChange(_ notification: Notification) {
+ guard let textview = notification.object as? NSTextView else {
+ return
+ }
+ self.parent.text = textview.string
+ }
+ }
+}
+
+private extension BetterTextEditor {
+ private func customized(_ customization: @escaping (NSTextView) -> Void) -> Self {
+ var copy = self
+ copy.customizations.append(customization)
+ return copy
+ }
+}
diff --git a/Hotline/Utility/FoundationExtensions.swift b/Hotline/Utility/FoundationExtensions.swift
index ebd179a..14e76d5 100644
--- a/Hotline/Utility/FoundationExtensions.swift
+++ b/Hotline/Utility/FoundationExtensions.swift
@@ -7,6 +7,28 @@ enum Endianness {
}
extension String {
+// func convertToPlainText() -> String {
+// var newString = self
+//
+// let map: [Character: Character] = [
+// "“": ",
+// "”": ",
+// "‘": "'",
+// "’": "'",
+// "\n": "\r"
+// ]
+//
+// newString = newString.replacingOccurrences(of: "\u{0060}", with: "'")
+// newString = newString.replacingOccurrences(of: "\u{00b4}", with: "'")
+// newString = newString.replacingOccurrences(of: "\u{2018}", with: "'")
+// newString = newString.replacingOccurrences(of: "\u{2019}", with: "'")
+// newString = newString.replacingOccurrences(of: "\u{201c}", with: "'")
+// newString = newString.replacingOccurrences(of: "\u{201d}", with: "'")
+// newString = newString.replacingOccurrences(of: "\"", with: "\"")
+//
+// return newString
+// }
+
func replyToString() -> String {
if self.range(of: "^Re:", options: [.regularExpression, .caseInsensitive]) != nil {
return String(self)
diff --git a/Hotline/macOS/MessageBoardEditorView.swift b/Hotline/macOS/MessageBoardEditorView.swift
new file mode 100644
index 0000000..1b49f4e
--- /dev/null
+++ b/Hotline/macOS/MessageBoardEditorView.swift
@@ -0,0 +1,117 @@
+import SwiftUI
+
+private enum FocusFields {
+ case body
+}
+
+struct MessageBoardEditorView: View {
+ @Environment(\.controlActiveState) private var controlActiveState
+ @Environment(\.colorScheme) private var colorScheme
+ @Environment(\.dismiss) private var dismiss
+ @Environment(Hotline.self) private var model: Hotline
+
+ @State private var text: String = ""
+ @State private var sending: Bool = false
+
+ @FocusState private var focusedField: FocusFields?
+
+ func sendPost() async {
+ sending = true
+
+ let cleanedText = text.trimmingCharacters(in: .whitespacesAndNewlines)
+
+ await model.postToMessageBoard(text: cleanedText)
+ let _ = await model.getMessageBoard()
+
+// let success = await model.postNewsArticle(title: title, body: text, at: path, parentID: parentID)
+// if success {
+// await model.getNewsList(at: path)
+// }
+
+ sending = false
+ }
+
+ var body: some View {
+ VStack(alignment: .leading, spacing: 0) {
+ HStack(alignment: .center, spacing: 0) {
+ Button {
+ dismiss()
+ } label: {
+ Image(systemName: "xmark")
+ .resizable()
+ .scaledToFit()
+ .frame(width: 14, height: 14)
+ .opacity(0.5)
+ }
+ .buttonStyle(.plain)
+ .frame(width: 16, height: 16)
+
+ Spacer()
+
+ Image("Message Board Post")
+ .resizable()
+ .scaledToFit()
+ .frame(width: 16, height: 16)
+ .padding(.trailing, 6)
+
+ Text("New Post")
+ .fontWeight(.semibold)
+ .lineLimit(1)
+ .truncationMode(.middle)
+
+ Spacer()
+
+ if sending {
+ ProgressView()
+ .controlSize(.small)
+ .frame(width: 22, height: 22)
+ }
+ else {
+ Button {
+ sending = true
+ model.postToMessageBoard(text: text)
+ Task {
+ let _ = await model.getMessageBoard()
+ Task { @MainActor in
+ sending = false
+ dismiss()
+ }
+ }
+ } label: {
+ Image(systemName: "arrow.up.circle.fill")
+ .resizable()
+ .renderingMode(.template)
+ .scaledToFit()
+ .foregroundColor(text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ? .secondary : .accentColor)
+ }
+ .buttonStyle(.plain)
+ .frame(width: 22, height: 22)
+ .help("Post to Message Board")
+ .disabled(text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty)
+ }
+ }
+ .frame(maxWidth: .infinity)
+ .padding()
+
+ Divider()
+
+ BetterTextEditor(text: $text)
+ .betterEditorFont(NSFont.systemFont(ofSize: 14.0))
+ .betterEditorAutomaticSpellingCorrection(true)
+ .betterEditorTextInset(.init(width: 16, height: 18))
+ .lineSpacing(20)
+ .background(Color(nsColor: .textBackgroundColor))
+ .frame(maxWidth: .infinity, maxHeight: .infinity)
+ .focused($focusedField, equals: .body)
+ }
+ .frame(minWidth: 300, idealWidth: 450, maxWidth: .infinity, minHeight: 300, idealHeight: 500, maxHeight: .infinity)
+ .background(Color(nsColor: .textBackgroundColor))
+ .presentationCompactAdaptation(.sheet)
+ .onAppear {
+ focusedField = .body
+ }
+ .onDisappear {
+ dismiss()
+ }
+ }
+}
diff --git a/Hotline/macOS/MessageBoardView.swift b/Hotline/macOS/MessageBoardView.swift
index 2bd3713..ba9968b 100644
--- a/Hotline/macOS/MessageBoardView.swift
+++ b/Hotline/macOS/MessageBoardView.swift
@@ -3,9 +3,8 @@ import SwiftUI
struct MessageBoardView: View {
@Environment(Hotline.self) private var model: Hotline
- @State private var initialLoadComplete = false
- @State private var composerDisplayed = false
- @State private var composerText = ""
+ @State private var composerDisplayed: Bool = false
+ @State private var composerText: String = ""
var body: some View {
NavigationStack {
@@ -54,31 +53,36 @@ struct MessageBoardView: View {
}
}
.sheet(isPresented: $composerDisplayed) {
- TextEditor(text: $composerText)
- .padding()
- .font(.system(size: 13))
- .lineSpacing(4)
- .background(Color(nsColor: .textBackgroundColor))
+ MessageBoardEditorView()
+ .frame(maxWidth: .infinity, maxHeight: .infinity)
.frame(idealWidth: 450, idealHeight: 350)
- .toolbar {
- ToolbarItem(placement: .cancellationAction) {
- Button("Cancel") {
- composerDisplayed.toggle()
- }
- }
-
- ToolbarItem(placement: .primaryAction) {
- Button("Post") {
- composerDisplayed.toggle()
- let text = composerText
- composerText = ""
- model.postToMessageBoard(text: text)
- Task {
- await model.getMessageBoard()
- }
- }
- }
- }
+// RichTextEditor(text: $composerText)
+// .richEditorFont(NSFont.systemFont(ofSize: 16.0))
+// .richEditorAutomaticDashSubstitution(false)
+// .richEditorAutomaticQuoteSubstitution(false)
+// .richEditorAutomaticSpellingCorrection(false)
+// .background(Color(nsColor: .textBackgroundColor))
+// .frame(maxWidth: .infinity, maxHeight: .infinity)
+// .frame(idealWidth: 450, idealHeight: 350)
+// .toolbar {
+// ToolbarItem(placement: .cancellationAction) {
+// Button("Cancel") {
+// composerDisplayed.toggle()
+// }
+// }
+//
+// ToolbarItem(placement: .primaryAction) {
+// Button("Post") {
+// composerDisplayed.toggle()
+// let text = composerText
+// composerText = ""
+// model.postToMessageBoard(text: text)
+// Task {
+// await model.getMessageBoard()
+// }
+// }
+// }
+// }
}
.toolbar {
ToolbarItem(placement:.primaryAction) {
diff --git a/Hotline/macOS/NewsEditorView.swift b/Hotline/macOS/NewsEditorView.swift
index ff33281..a6f72ec 100644
--- a/Hotline/macOS/NewsEditorView.swift
+++ b/Hotline/macOS/NewsEditorView.swift
@@ -110,17 +110,12 @@ struct NewsEditorView: View {
Divider()
- TextEditor(text: $text)
- .textEditorStyle(.plain)
- .font(.system(size: 14, design: .monospaced))
- .lineSpacing(3)
- .padding(16)
- .contentMargins(.top, -16.0, for: .scrollIndicators)
- .contentMargins(.bottom, -16.0, for: .scrollIndicators)
- .contentMargins(.trailing, -16.0, for: .scrollIndicators)
- .scrollClipDisabled()
+ BetterTextEditor(text: $text)
+ .betterEditorFont(NSFont.monospacedSystemFont(ofSize: 14.0, weight: .regular))
+ .betterEditorAutomaticSpellingCorrection(true)
+ .betterEditorTextInset(.init(width: 16, height: 18))
+ .background(Color(nsColor: .textBackgroundColor))
.frame(maxWidth: .infinity, maxHeight: .infinity)
- .clipped()
.focused($focusedField, equals: .body)
HStack(alignment: .center) {
@@ -147,6 +142,9 @@ struct NewsEditorView: View {
if !title.isEmpty {
focusedField = .body
}
+ else {
+ focusedField = .title
+ }
}
.onDisappear {
dismiss()
diff --git a/Hotline/macOS/NewsView.swift b/Hotline/macOS/NewsView.swift
index 8e10b19..4469585 100644
--- a/Hotline/macOS/NewsView.swift
+++ b/Hotline/macOS/NewsView.swift
@@ -58,7 +58,7 @@ struct NewsView: View {
)
.fraction(splitFraction)
.constraints(minPFraction: 0.1, minSFraction: 0.3)
-// .hide(splitHidden)
+ .hide(splitHidden)
.styling(color: colorScheme == .dark ? .black : Splitter.defaultColor, inset: 0, visibleThickness: 0.5, invisibleThickness: 5, hideSplitter: true)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color(nsColor: .textBackgroundColor))
diff --git a/Hotline/macOS/ServerView.swift b/Hotline/macOS/ServerView.swift
index e3f0596..e342f73 100644
--- a/Hotline/macOS/ServerView.swift
+++ b/Hotline/macOS/ServerView.swift
@@ -151,6 +151,12 @@ struct ServerView: View {
ServerMenuItem(type: .files, name: "Files", image: "folder"),
]
+ static var classicMenuItems: [ServerMenuItem] = [
+ ServerMenuItem(type: .chat, name: "Chat", image: "bubble"),
+ ServerMenuItem(type: .board, name: "Board", image: "pin"),
+ ServerMenuItem(type: .files, name: "Files", image: "folder"),
+ ]
+
enum FocusFields {
case address
case login
@@ -347,7 +353,8 @@ struct ServerView: View {
var navigationList: some View {
List(selection: $state.selection) {
- ForEach(ServerView.menuItems) { menuItem in
+ // Don't show news on older servers.
+ ForEach(model.serverVersion < 151 ? ServerView.classicMenuItems : ServerView.menuItems) { menuItem in
if menuItem.type == .chat {
ListItemView(icon: menuItem.image, title: menuItem.name, unread: model.unreadPublicChat).tag(menuItem.type)
}