Tusker/Tusker/Screens/Report/ReportView.swift

197 lines
6.8 KiB
Swift

//
// ReportView.swift
// Tusker
//
// Created by Shadowfacts on 1/13/23.
// Copyright © 2023 Shadowfacts. All rights reserved.
//
import SwiftUI
import TuskerComponents
struct ReportView: View {
let account: AccountMO
@ObservedObject var mastodonController: MastodonController
@StateObject var report: EditedReport
@Environment(\.dismiss) private var dismiss
@ObservedObject private var preferences = Preferences.shared
@State private var isReporting = false
@State private var error: Error?
init(report: EditedReport, mastodonController: MastodonController) {
self.account = mastodonController.persistentContainer.account(for: report.accountID)!
self.mastodonController = mastodonController
self._report = StateObject(wrappedValue: report)
if mastodonController.instance?.rules == nil {
report.reason = .spam
}
}
var body: some View {
if #available(iOS 16.0, *) {
NavigationStack {
navigationViewContent
.scrollDismissesKeyboard(.interactively)
}
} else {
NavigationView {
navigationViewContent
}
.navigationViewStyle(.stack)
}
}
private var navigationViewContent: some View {
Form {
Section {
HStack {
AvatarImageView(
url: account.avatar,
size: 50,
style: Preferences.shared.avatarStyle == .circle ? .circle : .roundRect,
fetchAvatar: { await ImageCache.avatars.get($0).1 }
)
VStack(alignment: .leading) {
AccountDisplayNameLabel(account: account, textStyle: .headline, emojiSize: 17)
Text("@\(account.acct)")
.fontWeight(.light)
.foregroundColor(.secondary)
}
}
.frame(height: 50)
.listRowBackground(EmptyView())
// vertical insets are so the rounded corners fo the section don't affect the avatar
.listRowInsets(EdgeInsets(top: 5, leading: 0, bottom: 5, trailing: 0))
}
.accessibilityHidden(true)
Section {
Button {
report.reason = .spam
} label: {
HStack {
Text("Spam")
Spacer()
if case .spam = report.reason {
Image(systemName: "checkmark")
}
}
}
if mastodonController.instance?.rules != nil {
NavigationLink {
ReportSelectRulesView(mastodonController: mastodonController, report: report)
} label: {
HStack {
Text("Instance Rule")
Spacer()
if case .rules(_) = report.reason {
Image(systemName: "checkmark")
}
}
.foregroundColor(.accentColor)
}
}
} header: {
Text("Reason")
}
.appGroupedListRowBackground()
Section {
ZStack(alignment: .topLeading) {
if report.comment.isEmpty {
Text("Add any additional comments")
.offset(x: 4, y: 8)
.foregroundColor(.secondary)
}
TextEditor(text: $report.comment)
.background(.clear)
.frame(minHeight: 100)
}
.font(.body)
.listRowInsets(EdgeInsets(top: 8, leading: 8, bottom: 8, trailing: 8))
}
.appGroupedListRowBackground()
Section {
ForEach(report.statusIDs, id: \.self) { id in
ReportStatusView(status: mastodonController.persistentContainer.status(for: id)!, mastodonController: mastodonController)
}
.onDelete { indices in
report.statusIDs.remove(atOffsets: indices)
}
NavigationLink {
ReportAddStatusView(report: report, mastodonController: mastodonController)
} label: {
Label("Add Posts…", systemImage: "plus")
.foregroundColor(.accentColor)
}
} footer: {
Text("Attach posts to your report to provide additional context for moderators.")
}
.appGroupedListRowBackground()
Section {
Toggle("Forward", isOn: $report.forward)
} footer: {
Text("You can choose to anonymously forward your report to the moderators of **\(account.url.host!)**.")
}
.appGroupedListRowBackground()
Button(action: self.sendReport) {
let label = Text(isReporting ? "Sending Report" : "Send Report")
HStack {
label
Spacer()
if isReporting {
ProgressView()
.progressViewStyle(.circular)
}
}
.accessibilityLabel(label)
}
.disabled(isReporting)
.appGroupedListRowBackground()
}
.listStyle(.insetGrouped)
.appGroupedListBackground(container: UIHostingController<ReportView>.self, applyBackground: true)
.alertWithData("Error Reporting", data: $error, actions: { error in
Button("OK") {}
}, message: { error in
Text(error.localizedDescription)
})
.navigationTitle("Report \(account.displayOrUserName)")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button("Cancel") {
self.dismiss()
}
}
}
}
private func sendReport() {
isReporting = true
Task {
do {
_ = try await mastodonController.run(report.makeRequest()!)
self.dismiss()
} catch {
self.error = error
self.isReporting = false
}
}
}
}
//struct ReportView_Previews: PreviewProvider {
// static var previews: some View {
// ReportView()
// }
//}