forked from shadowfacts/Tusker
Add reporting accounts and statuses
This commit is contained in:
parent
1ad556f9cf
commit
94c34e03dd
|
@ -323,11 +323,20 @@ public class Client {
|
|||
return Request<[Report]>(method: .get, path: "/api/v1/reports")
|
||||
}
|
||||
|
||||
public static func report(account: Account, statuses: [Status], comment: String) -> Request<Report> {
|
||||
public static func report(
|
||||
account: String,
|
||||
statuses: [String],
|
||||
comment: String,
|
||||
forward: Bool,
|
||||
category: String,
|
||||
ruleIDs: [String]
|
||||
) -> Request<Report> {
|
||||
return Request<Report>(method: .post, path: "/api/v1/reports", body: ParametersBody([
|
||||
"account_id" => account.id,
|
||||
"comment" => comment
|
||||
] + "status_ids" => statuses.map { $0.id }))
|
||||
"account_id" => account,
|
||||
"comment" => comment,
|
||||
"forward" => forward,
|
||||
"category" => category,
|
||||
] + "status_ids" => statuses + "rule_ids" => ruleIDs))
|
||||
}
|
||||
|
||||
// MARK: - Search
|
||||
|
|
|
@ -94,11 +94,12 @@ public final class Account: AccountProtocol, Decodable {
|
|||
return request
|
||||
}
|
||||
|
||||
public static func getStatuses(_ accountID: String, range: RequestRange = .default, onlyMedia: Bool? = nil, pinned: Bool? = nil, excludeReplies: Bool? = nil) -> Request<[Status]> {
|
||||
public static func getStatuses(_ accountID: String, range: RequestRange = .default, onlyMedia: Bool? = nil, pinned: Bool? = nil, excludeReplies: Bool? = nil, excludeReblogs: Bool? = nil) -> Request<[Status]> {
|
||||
var request = Request<[Status]>(method: .get, path: "/api/v1/accounts/\(accountID)/statuses", queryParameters: [
|
||||
"only_media" => onlyMedia,
|
||||
"pinned" => pinned,
|
||||
"exclude_replies" => excludeReplies
|
||||
"exclude_replies" => excludeReplies,
|
||||
"exclude_reblogs" => excludeReblogs,
|
||||
])
|
||||
request.range = range
|
||||
return request
|
||||
|
|
|
@ -20,6 +20,7 @@ public class Instance: Decodable {
|
|||
public let languages: [String]?
|
||||
public let stats: Stats?
|
||||
public let configuration: Configuration?
|
||||
public let rules: [Rule]?
|
||||
|
||||
// pleroma doesn't currently implement these
|
||||
public let contactAccount: Account?
|
||||
|
@ -57,6 +58,7 @@ public class Instance: Decodable {
|
|||
self.thumbnail = try? container.decodeIfPresent(URL.self, forKey: .thumbnail)
|
||||
|
||||
self.configuration = try? container.decodeIfPresent(Configuration.self, forKey: .configuration)
|
||||
self.rules = try? container.decodeIfPresent([Rule].self, forKey: .rules)
|
||||
|
||||
if let maxTootCharacters = try? container.decodeIfPresent(Int.self, forKey: .maxTootCharacters) {
|
||||
self.maxTootCharacters = maxTootCharacters
|
||||
|
@ -83,6 +85,7 @@ public class Instance: Decodable {
|
|||
case stats
|
||||
case configuration
|
||||
case contactAccount = "contact_account"
|
||||
case rules
|
||||
|
||||
case maxTootCharacters = "max_toot_chars"
|
||||
case pollLimits = "poll_limits"
|
||||
|
@ -167,3 +170,10 @@ extension Instance {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Instance {
|
||||
public struct Rule: Decodable, Identifiable {
|
||||
public let id: String
|
||||
public let text: String
|
||||
}
|
||||
}
|
||||
|
|
|
@ -145,6 +145,11 @@
|
|||
D6552367289870790048A653 /* ScreenCorners in Frameworks */ = {isa = PBXBuildFile; productRef = D6552366289870790048A653 /* ScreenCorners */; };
|
||||
D659F35E2953A212002D944A /* TTTKit in Frameworks */ = {isa = PBXBuildFile; productRef = D659F35D2953A212002D944A /* TTTKit */; };
|
||||
D659F36229541065002D944A /* TTTView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D659F36129541065002D944A /* TTTView.swift */; };
|
||||
D65B4B542971F71D00DABDFB /* EditedReport.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65B4B532971F71D00DABDFB /* EditedReport.swift */; };
|
||||
D65B4B562971F98300DABDFB /* ReportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65B4B552971F98300DABDFB /* ReportView.swift */; };
|
||||
D65B4B58297203A700DABDFB /* ReportSelectRulesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65B4B57297203A700DABDFB /* ReportSelectRulesView.swift */; };
|
||||
D65B4B5A29720AB000DABDFB /* ReportStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65B4B5929720AB000DABDFB /* ReportStatusView.swift */; };
|
||||
D65B4B5E2973040D00DABDFB /* ReportAddStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65B4B5D2973040D00DABDFB /* ReportAddStatusView.swift */; };
|
||||
D65C6BF525478A9C00A6E89C /* BackgroundableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65C6BF425478A9C00A6E89C /* BackgroundableViewController.swift */; };
|
||||
D65F613423AEAB6600F3CFD3 /* OnboardingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65F613323AEAB6600F3CFD3 /* OnboardingTests.swift */; };
|
||||
D6620ACE2511A0ED00312CA0 /* StatusStateResolver.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6620ACD2511A0ED00312CA0 /* StatusStateResolver.swift */; };
|
||||
|
@ -527,6 +532,11 @@
|
|||
D6538944214D6D7500E3CEFC /* TableViewSwipeActionProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableViewSwipeActionProvider.swift; sourceTree = "<group>"; };
|
||||
D653F410267D1E32004E32B1 /* DiffableTimelineLikeTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiffableTimelineLikeTableViewController.swift; sourceTree = "<group>"; };
|
||||
D659F36129541065002D944A /* TTTView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TTTView.swift; sourceTree = "<group>"; };
|
||||
D65B4B532971F71D00DABDFB /* EditedReport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditedReport.swift; sourceTree = "<group>"; };
|
||||
D65B4B552971F98300DABDFB /* ReportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportView.swift; sourceTree = "<group>"; };
|
||||
D65B4B57297203A700DABDFB /* ReportSelectRulesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportSelectRulesView.swift; sourceTree = "<group>"; };
|
||||
D65B4B5929720AB000DABDFB /* ReportStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportStatusView.swift; sourceTree = "<group>"; };
|
||||
D65B4B5D2973040D00DABDFB /* ReportAddStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportAddStatusView.swift; sourceTree = "<group>"; };
|
||||
D65C6BF425478A9C00A6E89C /* BackgroundableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundableViewController.swift; sourceTree = "<group>"; };
|
||||
D65F612D23AE990C00F3CFD3 /* Embassy.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Embassy.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D65F613023AE99E000F3CFD3 /* Ambassador.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Ambassador.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
|
@ -810,6 +820,7 @@
|
|||
D677284D24ECC01D00C732D3 /* Draft.swift */,
|
||||
D627FF75217E923E00CC0648 /* DraftsManager.swift */,
|
||||
D61F75AE293AF50C00C0B37F /* EditedFilter.swift */,
|
||||
D65B4B532971F71D00DABDFB /* EditedReport.swift */,
|
||||
);
|
||||
path = Models;
|
||||
sourceTree = "<group>";
|
||||
|
@ -963,6 +974,7 @@
|
|||
D641C783213DD7FE004B4513 /* Onboarding */,
|
||||
D641C789213DD87E004B4513 /* Preferences */,
|
||||
D641C784213DD819004B4513 /* Profile */,
|
||||
D65B4B522971F6E300DABDFB /* Report */,
|
||||
D6BC9DD8232D8BCA002CA326 /* Search */,
|
||||
D6A3BC8C2321FF9B00FD64D5 /* Status Action Account List */,
|
||||
D641C781213DD7DD004B4513 /* Timeline */,
|
||||
|
@ -1173,6 +1185,17 @@
|
|||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D65B4B522971F6E300DABDFB /* Report */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D65B4B552971F98300DABDFB /* ReportView.swift */,
|
||||
D65B4B57297203A700DABDFB /* ReportSelectRulesView.swift */,
|
||||
D65B4B5929720AB000DABDFB /* ReportStatusView.swift */,
|
||||
D65B4B5D2973040D00DABDFB /* ReportAddStatusView.swift */,
|
||||
);
|
||||
path = Report;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D663626021360A9600C9CBA2 /* Preferences */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -1975,6 +1998,7 @@
|
|||
D64AAE9726C88DC400FC57FB /* ToastConfiguration.swift in Sources */,
|
||||
D63661C02381C144004B9E16 /* PreferencesNavigationController.swift in Sources */,
|
||||
D6E9CDA8281A427800BBC98E /* PostService.swift in Sources */,
|
||||
D65B4B5E2973040D00DABDFB /* ReportAddStatusView.swift in Sources */,
|
||||
D6B053A223BD2C0600A066FA /* AssetPickerViewController.swift in Sources */,
|
||||
D6EE63FB2551F7F60065485C /* StatusCollapseButton.swift in Sources */,
|
||||
D6CA8CDE296387310050C433 /* SaveToPhotosActivity.swift in Sources */,
|
||||
|
@ -2020,6 +2044,7 @@
|
|||
D6BEA24B291C6A2B002F4D01 /* AlertWithData.swift in Sources */,
|
||||
D61ABEFE28F1C92600B29151 /* FavoriteService.swift in Sources */,
|
||||
D61F75AB293AF11400C0B37F /* FilterKeywordMO.swift in Sources */,
|
||||
D65B4B5A29720AB000DABDFB /* ReportStatusView.swift in Sources */,
|
||||
D663626221360B1900C9CBA2 /* Preferences.swift in Sources */,
|
||||
D626493823C0FD0000612E6E /* AllPhotosTableViewCell.swift in Sources */,
|
||||
D627943B23A55BA600D38C68 /* NavigableTableViewCell.swift in Sources */,
|
||||
|
@ -2065,7 +2090,9 @@
|
|||
D6FF9860255C717400845181 /* AccountSwitchingContainerViewController.swift in Sources */,
|
||||
D6E77D0B286D426E00D8B732 /* TrendingLinkCardCollectionViewCell.swift in Sources */,
|
||||
D6114E1127F899B30080E273 /* TrendingLinksViewController.swift in Sources */,
|
||||
D65B4B58297203A700DABDFB /* ReportSelectRulesView.swift in Sources */,
|
||||
D6B81F442560390300F6E31D /* MenuController.swift in Sources */,
|
||||
D65B4B542971F71D00DABDFB /* EditedReport.swift in Sources */,
|
||||
D65234E12561AA68001AF9CF /* NotificationsTableViewController.swift in Sources */,
|
||||
D6A6C11525B62E9700298D0F /* CacheExpiry.swift in Sources */,
|
||||
D67C57AF21E28EAD00C3118B /* Array+Uniques.swift in Sources */,
|
||||
|
@ -2127,6 +2154,7 @@
|
|||
D6C82B4125C5BB7E0017F1E6 /* ExploreViewController.swift in Sources */,
|
||||
D6B053A423BD2C8100A066FA /* AssetCollectionsListViewController.swift in Sources */,
|
||||
D6A3A380295515550036B6EF /* ProfileHeaderButton.swift in Sources */,
|
||||
D65B4B562971F98300DABDFB /* ReportView.swift in Sources */,
|
||||
D623A543263634100095BD04 /* PollOptionCheckboxView.swift in Sources */,
|
||||
D68A76E829527884001DA1B3 /* PinnedTimelinesView.swift in Sources */,
|
||||
D690797324A4EF9700023A34 /* UIBezierPath+Helpers.swift in Sources */,
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
//
|
||||
// EditedReport.swift
|
||||
// Tusker
|
||||
//
|
||||
// Created by Shadowfacts on 1/13/23.
|
||||
// Copyright © 2023 Shadowfacts. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Pachyderm
|
||||
|
||||
class EditedReport: ObservableObject {
|
||||
let accountID: String
|
||||
@Published var statusIDs = [String]()
|
||||
@Published var comment = ""
|
||||
@Published var forward = false
|
||||
@Published var reason: Reason = .spam
|
||||
|
||||
init(accountID: String) {
|
||||
self.accountID = accountID
|
||||
}
|
||||
|
||||
func makeRequest() -> Request<Report>? {
|
||||
let category: String
|
||||
let ruleIDs: [String]
|
||||
switch reason {
|
||||
case .spam:
|
||||
category = "spam"
|
||||
ruleIDs = []
|
||||
case .rules(let ids):
|
||||
category = "violation"
|
||||
ruleIDs = ids
|
||||
}
|
||||
return Client.report(account: accountID, statuses: statusIDs, comment: comment, forward: forward, category: category, ruleIDs: ruleIDs)
|
||||
}
|
||||
}
|
||||
|
||||
extension EditedReport {
|
||||
enum Reason {
|
||||
case spam
|
||||
case rules([String])
|
||||
}
|
||||
}
|
|
@ -69,7 +69,8 @@ struct MuteAccountView: View {
|
|||
}
|
||||
.frame(height: 50)
|
||||
.listRowBackground(EmptyView())
|
||||
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
|
||||
// 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)
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
//
|
||||
// ReportAddStatusView.swift
|
||||
// Tusker
|
||||
//
|
||||
// Created by Shadowfacts on 1/14/23.
|
||||
// Copyright © 2023 Shadowfacts. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Pachyderm
|
||||
|
||||
struct ReportAddStatusView: View {
|
||||
@ObservedObject var report: EditedReport
|
||||
let mastodonController: MastodonController
|
||||
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
@State private var statuses: [StatusMO]?
|
||||
@State private var error: Error?
|
||||
|
||||
var body: some View {
|
||||
statusesListIfLoaded
|
||||
.navigationTitle("Add Posts")
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var statusesListIfLoaded: some View {
|
||||
if let statuses {
|
||||
List {
|
||||
ForEach(statuses, id: \.id) { status in
|
||||
Button {
|
||||
report.statusIDs.append(status.id)
|
||||
dismiss()
|
||||
} label: {
|
||||
ReportStatusView(status: status, mastodonController: mastodonController)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ProgressView()
|
||||
.progressViewStyle(.circular)
|
||||
.alertWithData("Error Loading Posts", data: $error, actions: { _ in
|
||||
Button("OK") {}
|
||||
}, message: { error in
|
||||
Text(error.localizedDescription)
|
||||
})
|
||||
.task { @MainActor in
|
||||
do {
|
||||
let req = Account.getStatuses(report.accountID, excludeReplies: false, excludeReblogs: true)
|
||||
let (statuses, _) = try await mastodonController.run(req)
|
||||
await mastodonController.persistentContainer.addAll(statuses: statuses)
|
||||
self.statuses = statuses.compactMap { mastodonController.persistentContainer.status(for: $0.id) }
|
||||
} catch {
|
||||
self.error = error
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
//
|
||||
// ReportSelectRulesView.swift
|
||||
// Tusker
|
||||
//
|
||||
// Created by Shadowfacts on 1/13/23.
|
||||
// Copyright © 2023 Shadowfacts. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ReportSelectRulesView: View {
|
||||
@ObservedObject var mastodonController: MastodonController
|
||||
@ObservedObject var report: EditedReport
|
||||
|
||||
var selectedRuleIDs: [String] {
|
||||
get {
|
||||
if case .rules(let ids) = report.reason {
|
||||
return ids
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
}
|
||||
nonmutating set {
|
||||
report.reason = .rules(newValue)
|
||||
}
|
||||
}
|
||||
|
||||
init(mastodonController: MastodonController, report: EditedReport) {
|
||||
self.mastodonController = mastodonController
|
||||
self.report = report
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
List(mastodonController.instance.rules!) { rule in
|
||||
Button {
|
||||
if selectedRuleIDs.contains(rule.id) {
|
||||
selectedRuleIDs.removeAll(where: { $0 == rule.id })
|
||||
} else {
|
||||
selectedRuleIDs.append(rule.id)
|
||||
}
|
||||
} label: {
|
||||
HStack {
|
||||
Text(rule.text)
|
||||
.foregroundColor(.primary)
|
||||
Spacer()
|
||||
Image(systemName: "checkmark")
|
||||
.foregroundColor(selectedRuleIDs.contains(rule.id) ? .accentColor : .clear)
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("Rules")
|
||||
}
|
||||
}
|
||||
|
||||
//struct ReportSelectRulesView_Previews: PreviewProvider {
|
||||
// static var previews: some View {
|
||||
// ReportSelectRulesView()
|
||||
// }
|
||||
//}
|
|
@ -0,0 +1,38 @@
|
|||
//
|
||||
// ReportStatusView.swift
|
||||
// Tusker
|
||||
//
|
||||
// Created by Shadowfacts on 1/13/23.
|
||||
// Copyright © 2023 Shadowfacts. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import SwiftSoup
|
||||
|
||||
private var converter = HTMLConverter()
|
||||
|
||||
struct ReportStatusView: View {
|
||||
let status: StatusMO
|
||||
let mastodonController: MastodonController
|
||||
|
||||
private var text: AttributedString {
|
||||
let str = AttributedString(converter.convert(status.content))
|
||||
return str.transformingAttributes(\.link) { transformer in
|
||||
if transformer.value != nil {
|
||||
transformer.replace(with: \.foregroundColor, value: .accentColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
Text(text)
|
||||
|
||||
if !status.attachments.isEmpty {
|
||||
Text("^[\(status.attachments.count) attachments](inflect: true)")
|
||||
.foregroundColor(.secondary)
|
||||
.font(.caption.bold())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
//
|
||||
// ReportView.swift
|
||||
// Tusker
|
||||
//
|
||||
// Created by Shadowfacts on 1/13/23.
|
||||
// Copyright © 2023 Shadowfacts. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
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
|
||||
}
|
||||
} else {
|
||||
NavigationView {
|
||||
navigationViewContent
|
||||
}
|
||||
.navigationViewStyle(.stack)
|
||||
}
|
||||
}
|
||||
|
||||
private var navigationViewContent: some View {
|
||||
Form {
|
||||
Section {
|
||||
HStack {
|
||||
ComposeAvatarImageView(url: account.avatar)
|
||||
.frame(width: 50, height: 50)
|
||||
.cornerRadius(preferences.avatarStyle.cornerRadiusFraction * 50)
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
Section {
|
||||
ComposeTextView(text: $report.comment, placeholder: Text("Add any additional comments"))
|
||||
.backgroundColor(.clear)
|
||||
.listRowInsets(EdgeInsets(top: 8, leading: 8, bottom: 8, trailing: 8))
|
||||
}
|
||||
|
||||
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.")
|
||||
}
|
||||
|
||||
Section {
|
||||
Toggle("Forward", isOn: $report.forward)
|
||||
} footer: {
|
||||
Text("You can choose to anonymously forward your report to the moderators of **\(account.url.host!)**.")
|
||||
}
|
||||
|
||||
Button(action: self.sendReport) {
|
||||
if isReporting {
|
||||
Text("Sending Report")
|
||||
Spacer()
|
||||
ProgressView()
|
||||
.progressViewStyle(.circular)
|
||||
} else {
|
||||
Text("Send Report")
|
||||
}
|
||||
}
|
||||
.disabled(isReporting)
|
||||
}
|
||||
.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()
|
||||
// }
|
||||
//}
|
|
@ -84,6 +84,11 @@ extension MenuActionProvider {
|
|||
}))
|
||||
suppressSection.append(relationshipAction(fetchRelationship, accountID: accountID, mastodonController: mastodonController, builder: { [unowned self] in self.blockAction(for: $0, mastodonController: $1) }))
|
||||
suppressSection.append(relationshipAction(fetchRelationship, accountID: accountID, mastodonController: mastodonController, builder: { [unowned self] in self.muteAction(for: $0, mastodonController: $1) }))
|
||||
suppressSection.append(createAction(identifier: "report", title: "Report", systemImageName: "flag", handler: { [unowned self] _ in
|
||||
let view = ReportView(report: EditedReport(accountID: accountID), mastodonController: mastodonController)
|
||||
let host = UIHostingController(rootView: view)
|
||||
self.navigationDelegate?.present(host, animated: true)
|
||||
}))
|
||||
}
|
||||
|
||||
addOpenInNewWindow(actions: &shareSection, activity: UserActivityManager.showProfileActivity(id: accountID, accountID: loggedInAccountID))
|
||||
|
@ -210,7 +215,15 @@ extension MenuActionProvider {
|
|||
}), at: 1)
|
||||
}
|
||||
|
||||
var actionsSection: [UIAction] = []
|
||||
var actionsSection: [UIAction] = [
|
||||
createAction(identifier: "report", title: "Report", systemImageName: "flag", handler: { [weak self] _ in
|
||||
let report = EditedReport(accountID: status.account.id)
|
||||
report.statusIDs = [status.id]
|
||||
let view = ReportView(report: report, mastodonController: mastodonController)
|
||||
let host = UIHostingController(rootView: view)
|
||||
self?.navigationDelegate?.present(host, animated: true)
|
||||
})
|
||||
]
|
||||
|
||||
if includeStatusButtonActions {
|
||||
actionsSection.insert(createAction(identifier: "reply", title: "Reply", systemImageName: "arrowshape.turn.up.left", handler: { [weak self] (_) in
|
||||
|
|
Loading…
Reference in New Issue