// // Draft.swift // Tusker // // Created by Shadowfacts on 8/18/20. // Copyright © 2020 Shadowfacts. All rights reserved. // import Foundation import Pachyderm class Draft: Codable, ObservableObject { let id: UUID var lastModified: Date @Published var accountID: String @Published var text: String @Published var contentWarningEnabled: Bool @Published var contentWarning: String @Published var attachments: [CompositionAttachment] @Published var inReplyToID: String? @Published var visibility: Status.Visibility var initialText: String var hasContent: Bool { (!text.isEmpty && text != initialText) || (contentWarningEnabled && !contentWarning.isEmpty) || attachments.count > 0 } init(accountID: String) { self.id = UUID() self.lastModified = Date() self.accountID = accountID self.text = "" self.contentWarningEnabled = false self.contentWarning = "" self.attachments = [] self.inReplyToID = nil self.visibility = Preferences.shared.defaultPostVisibility self.initialText = "" } required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) self.id = try container.decode(UUID.self, forKey: .id) self.lastModified = try container.decode(Date.self, forKey: .lastModified) self.accountID = try container.decode(String.self, forKey: .accountID) self.text = try container.decode(String.self, forKey: .text) if let enabled = try? container.decode(Bool.self, forKey: .contentWarningEnabled) { self.contentWarningEnabled = enabled self.contentWarning = try container.decode(String.self, forKey: .contentWarning) } else { // todo: temporary until migration away from old drafts manager is complete let cw = try container.decode(String?.self, forKey: .contentWarning) if let cw = cw { self.contentWarningEnabled = !cw.isEmpty self.contentWarning = cw } else { self.contentWarningEnabled = false self.contentWarning = "" } } self.attachments = try container.decode([CompositionAttachment].self, forKey: .attachments) self.inReplyToID = try container.decode(String?.self, forKey: .inReplyToID) self.visibility = try container.decode(Status.Visibility.self, forKey: .visibility) self.initialText = try container.decode(String.self, forKey: .initialText) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(id, forKey: .id) try container.encode(lastModified, forKey: .lastModified) try container.encode(accountID, forKey: .accountID) try container.encode(text, forKey: .text) try container.encode(contentWarningEnabled, forKey: .contentWarningEnabled) try container.encode(contentWarning, forKey: .contentWarning) try container.encode(attachments, forKey: .attachments) try container.encode(inReplyToID, forKey: .inReplyToID) try container.encode(visibility, forKey: .visibility) try container.encode(initialText, forKey: .initialText) } } extension Draft: Equatable { static func ==(lhs: Draft, rhs: Draft) -> Bool { return lhs.id == rhs.id } } extension Draft { enum CodingKeys: String, CodingKey { case id case lastModified case accountID case text case contentWarningEnabled case contentWarning case attachments case inReplyToID case visibility case initialText } } extension MastodonController { func createDraft(inReplyToID: String? = nil, mentioningAcct: String? = nil) -> Draft { var acctsToMention = [String]() var visibility = Preferences.shared.defaultPostVisibility var contentWarning = "" if let inReplyToID = inReplyToID, let inReplyTo = persistentContainer.status(for: inReplyToID) { acctsToMention.append(inReplyTo.account.acct) acctsToMention.append(contentsOf: inReplyTo.mentions.map(\.acct)) visibility = inReplyTo.visibility if !inReplyTo.spoilerText.isEmpty { switch Preferences.shared.contentWarningCopyMode { case .doNotCopy: break case .asIs: contentWarning = inReplyTo.spoilerText case .prependRe: if inReplyTo.spoilerText.lowercased().starts(with: "re:") { contentWarning = inReplyTo.spoilerText } else { contentWarning = "re: \(inReplyTo.spoilerText)" } } } } if let mentioningAcct = mentioningAcct { acctsToMention.append(mentioningAcct) } if let ownAccount = self.account { acctsToMention.removeAll(where: { $0 == ownAccount.acct }) } acctsToMention = acctsToMention.uniques() let draft = Draft(accountID: accountInfo!.id) draft.inReplyToID = inReplyToID draft.text = acctsToMention.map { "@\($0) " }.joined() draft.initialText = draft.text draft.visibility = visibility draft.contentWarning = contentWarning draft.contentWarningEnabled = !contentWarning.isEmpty return draft } }