diff options
| author | Dustin Mierau <dustin@mierau.me> | 2024-05-14 13:35:26 -0700 |
|---|---|---|
| committer | Dustin Mierau <dustin@mierau.me> | 2024-05-14 13:35:26 -0700 |
| commit | 87e979fb48da4a46e64544cea3e7b7d5fc32caa1 (patch) | |
| tree | 4c10cdba5a88544543bf45ae454f643decf1358c /Hotline/macOS/NewsEditorView.swift | |
| parent | e9fcf8c3b14e77479a6fb471bb51cd82a008147c (diff) | |
Newsgroup posting now works. Added reload button to news. More work on server and user icons.
Diffstat (limited to 'Hotline/macOS/NewsEditorView.swift')
| -rw-r--r-- | Hotline/macOS/NewsEditorView.swift | 189 |
1 files changed, 122 insertions, 67 deletions
diff --git a/Hotline/macOS/NewsEditorView.swift b/Hotline/macOS/NewsEditorView.swift index 18c4a0d..ff33281 100644 --- a/Hotline/macOS/NewsEditorView.swift +++ b/Hotline/macOS/NewsEditorView.swift @@ -1,5 +1,9 @@ import SwiftUI -import UniformTypeIdentifiers + +private enum FocusFields { + case title + case body +} struct NewsEditorView: View { @Environment(\.controlActiveState) private var controlActiveState @@ -7,94 +11,145 @@ struct NewsEditorView: View { @Environment(\.dismiss) private var dismiss @Environment(Hotline.self) private var model: Hotline -// @Binding var article: NewsArticle? + let editorTitle: String + let isReply: Bool + let path: [String] + let parentID: UInt32 + @State var title: String = "" - @State var text: String = "" + @State private var text: String = "" + @State private var sending: Bool = false + + @FocusState private var focusedField: FocusFields? + + func sendArticle() async -> Bool { + sending = true + + let success = await model.postNewsArticle(title: title, body: text, at: path, parentID: parentID) + if success { + await model.getNewsList(at: path) + } + + sending = false + + return success + } var body: some View { - NavigationStack { - VStack(alignment: .leading, spacing: 0) { - HStack { - Button { - dismiss() - } label: { - Image(systemName: "xmark.circle.fill") - .resizable() - .scaledToFit() - } - .buttonStyle(.plain) - .frame(width: 16, height: 16) - .padding() - - Spacer() - + 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() + + if !isReply { + Image("News Category") + .resizable() + .scaledToFit() + .frame(width: 16, height: 16) + .padding(.trailing, 6) + } + + Text(editorTitle) + .fontWeight(.semibold) + .lineLimit(1) + .truncationMode(.middle) + + Spacer() + + if sending { + ProgressView() + .controlSize(.small) + .frame(width: 22, height: 22) + } + else { Button { + Task { + if await sendArticle() { + dismiss() + } + } } label: { - Image(systemName: "paperplane") + Image(systemName: "arrow.up.circle.fill") .resizable() + .renderingMode(.template) .scaledToFit() + .foregroundColor((title.isEmpty || text.isEmpty) ? .secondary : .accentColor) } .buttonStyle(.plain) - .frame(width: 16, height: 16) - .padding() + .frame(width: 22, height: 22) + .help("Post to Newsgroup") + .disabled(title.isEmpty || text.isEmpty) } + } + .frame(maxWidth: .infinity) + .padding([.leading, .top, .trailing]) + + TextField("Title", text: $title, axis: .vertical) + .textFieldStyle(.plain) + .lineLimit(3) + .padding() + .focusEffectDisabled() + .fontWeight(.semibold) .frame(maxWidth: .infinity) - TextField("Title", text: $title, axis: .vertical) - .textFieldStyle(.plain) + .border(Color.pink, width: 0) + .background(.tertiary.opacity(0.2)) + .clipShape(RoundedRectangle(cornerRadius: 8)) + .padding() + .focused($focusedField, equals: .title) + + 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() + .frame(maxWidth: .infinity, maxHeight: .infinity) + .clipped() + .focused($focusedField, equals: .body) + + HStack(alignment: .center) { + Spacer() + + Text(String("**bold** _italics_ [link name](url) ")) + .foregroundStyle(.secondary) + .font(.caption) + .fontDesign(.monospaced) + .lineLimit(1) + .truncationMode(.middle) .padding() - .focusEffectDisabled() - .font(.title) - .frame(maxWidth: .infinity) - .border(Color.pink, width: 0) - Divider() - TextEditor(text: $text) - .textEditorStyle(.plain) - .font(.system(size: 14)) - .lineSpacing(3) - .padding(16) - .contentMargins(.top, -16.0, for: .scrollIndicators) - .contentMargins(.bottom, -16.0, for: .scrollIndicators) - .contentMargins(.trailing, -16.0, for: .scrollIndicators) - .scrollClipDisabled() - .frame(maxWidth: .infinity, maxHeight: .infinity) + + Spacer() } + .frame(maxWidth: .infinity) + .background(.tertiary.opacity(0.15)) } .frame(minWidth: 300, idealWidth: 450, maxWidth: .infinity, minHeight: 300, idealHeight: 500, maxHeight: .infinity) .background(Color(nsColor: .textBackgroundColor)) .presentationCompactAdaptation(.sheet) .toolbarTitleDisplayMode(.inlineLarge) -// .toolbar { -// ToolbarItem(placement: .navigation) { -// Button("Post", action: {}) -// } -// ToolbarItem(placement: .automatic) { -// Button("Delete", action: { -// dismiss() -// }) -// } -// } - .task { -// if let info = info { -// preview = FilePreview(info: info) -// preview?.download() -// } - } .onAppear { -// if info == nil { -// Task { -// dismiss() -// } -// return -// } + if !title.isEmpty { + focusedField = .body + } } .onDisappear { -// preview?.cancel() dismiss() } -// .onChange(of: preview?.state) { -// if preview?.state == .failed { -// dismiss() -// } -// } } } |