Compare commits

..

2 Commits

Author SHA1 Message Date
Shadowfacts 59277ec64f
Change drafts to store which accounts was used to create them
When loading a draft:

If the draft was created from a different account than the current one:
    If the draft was in reply to a status, don't allow it to be loaded.
    If the draft was not in reply to a status, prompt the user whether
    or not to load the draft.
If the draft was in reply to a different status than the current one:
    Prompt the user whether or not to load the draft.
Otherwise, load the draft.

Draft replies created from other accounts can't be loaded from different
accounts because the status for inReplyToID of the draft will have a
different instance-local ID if the two accounts are on different
instances.

See #16
2020-01-20 15:26:25 -05:00
Shadowfacts 08086f1b18
Fix compose reply view missing MastodonController instance 2020-01-20 15:25:23 -05:00
5 changed files with 61 additions and 10 deletions

View File

@ -39,8 +39,8 @@ class DraftsManager: Codable {
return drafts.sorted(by: { $0.lastModified > $1.lastModified }) return drafts.sorted(by: { $0.lastModified > $1.lastModified })
} }
func create(text: String, contentWarning: String?, inReplyToID: String?, attachments: [DraftAttachment]) -> Draft { func create(accountID: String, text: String, contentWarning: String?, inReplyToID: String?, attachments: [DraftAttachment]) -> Draft {
let draft = Draft(text: text, contentWarning: contentWarning, inReplyToID: inReplyToID, attachments: attachments) let draft = Draft(accountID: accountID, text: text, contentWarning: contentWarning, inReplyToID: inReplyToID, attachments: attachments)
drafts.append(draft) drafts.append(draft)
return draft return draft
} }
@ -55,14 +55,16 @@ class DraftsManager: Codable {
extension DraftsManager { extension DraftsManager {
class Draft: Codable, Equatable { class Draft: Codable, Equatable {
let id: UUID let id: UUID
private(set) var accountID: String
private(set) var text: String private(set) var text: String
private(set) var contentWarning: String? private(set) var contentWarning: String?
private(set) var attachments: [DraftAttachment] private(set) var attachments: [DraftAttachment]
private(set) var inReplyToID: String? private(set) var inReplyToID: String?
private(set) var lastModified: Date private(set) var lastModified: Date
init(text: String, contentWarning: String?, inReplyToID: String?, attachments: [DraftAttachment], lastModified: Date = Date()) { init(accountID: String, text: String, contentWarning: String?, inReplyToID: String?, attachments: [DraftAttachment], lastModified: Date = Date()) {
self.id = UUID() self.id = UUID()
self.accountID = accountID
self.text = text self.text = text
self.contentWarning = contentWarning self.contentWarning = contentWarning
self.inReplyToID = inReplyToID self.inReplyToID = inReplyToID
@ -70,7 +72,8 @@ extension DraftsManager {
self.lastModified = lastModified self.lastModified = lastModified
} }
func update(text: String, contentWarning: String?, attachments: [DraftAttachment]) { func update(accountID: String, text: String, contentWarning: String?, attachments: [DraftAttachment]) {
self.accountID = accountID
self.text = text self.text = text
self.contentWarning = contentWarning self.contentWarning = contentWarning
self.lastModified = Date() self.lastModified = Date()

View File

@ -101,6 +101,10 @@ class LocalData: ObservableObject {
accounts.removeAll(where: { $0.id == info.id }) accounts.removeAll(where: { $0.id == info.id })
} }
func getAccount(id: String) -> UserAccountInfo? {
return accounts.first(where: { $0.id == id })
}
func getMostRecentAccount() -> UserAccountInfo? { func getMostRecentAccount() -> UserAccountInfo? {
guard onboardingComplete else { return nil } guard onboardingComplete else { return nil }
let mostRecent: UserAccountInfo? let mostRecent: UserAccountInfo?

View File

@ -193,6 +193,7 @@ class ComposeViewController: UIViewController {
} }
let replyView = ComposeStatusReplyView.create() let replyView = ComposeStatusReplyView.create()
replyView.mastodonController = mastodonController
replyView.updateUI(for: inReplyTo) replyView.updateUI(for: inReplyTo)
stackView.insertArrangedSubview(replyView, at: 0) stackView.insertArrangedSubview(replyView, at: 0)
@ -367,10 +368,11 @@ class ComposeViewController: UIViewController {
attachments.append(.init(attachment: attachment, description: description)) attachments.append(.init(attachment: attachment, description: description))
} }
let cw = contentWarningEnabled ? contentWarningTextField.text : nil let cw = contentWarningEnabled ? contentWarningTextField.text : nil
let account = mastodonController.accountInfo!
if let currentDraft = self.currentDraft { if let currentDraft = self.currentDraft {
currentDraft.update(text: self.statusTextView.text, contentWarning: cw, attachments: attachments) currentDraft.update(accountID: account.id, text: self.statusTextView.text, contentWarning: cw, attachments: attachments)
} else { } else {
self.currentDraft = DraftsManager.shared.create(text: self.statusTextView.text, contentWarning: cw, inReplyToID: inReplyToID, attachments: attachments) self.currentDraft = DraftsManager.shared.create(accountID: account.id, text: self.statusTextView.text, contentWarning: cw, inReplyToID: inReplyToID, attachments: attachments)
} }
DraftsManager.save() DraftsManager.save()
} }
@ -621,8 +623,46 @@ extension ComposeViewController: DraftsTableViewControllerDelegate {
} }
func shouldSelectDraft(_ draft: DraftsManager.Draft, completion: @escaping (Bool) -> Void) { func shouldSelectDraft(_ draft: DraftsManager.Draft, completion: @escaping (Bool) -> Void) {
if draft.inReplyToID != self.inReplyToID { if draft.accountID != mastodonController.accountInfo!.id {
// todo: better text for this let currentAccount = mastodonController.accountInfo!
let currentAcct = "\(currentAccount.username)@\(currentAccount.instanceURL.host!)"
let otherAccount = LocalData.shared.getAccount(id: draft.accountID)
let otherAcct: String!
if let otherAccount = otherAccount {
otherAcct = "\(otherAccount.username)@\(otherAccount.instanceURL.host!)"
} else {
otherAcct = nil
}
if draft.inReplyToID != nil {
let message: String
if otherAccount != nil {
message = "The selected draft is a reply from a different account, it cannot be loaded from this account. To use it, switch accounts to \(otherAcct!)"
} else {
message = "The selected draft is a reply from an account that has been logged-out of. It cannot be loaded."
}
let alertController = UIAlertController(title: "Reply from Different Account", message: message, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (_) in
completion(false)
}))
presentedViewController!.present(alertController, animated: true)
} else {
let message: String
if otherAccount != nil {
message = "The selected draft is from a different account (\(otherAcct!)) than your currently active account (\(currentAcct)). Do you wish to load it anyway?"
} else {
message = "The selected draft from an account that has been logged-out of."
}
let alertController = UIAlertController(title: "Draft from Different Account", message: message, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { (_) in
completion(false)
}))
alertController.addAction(UIAlertAction(title: "Load Draft", style: .default, handler: { (_) in
completion(true)
}))
presentedViewController!.present(alertController, animated: true)
}
} else if draft.inReplyToID != self.inReplyToID {
let alertController = UIAlertController(title: "Different Reply", message: "The selected draft is a reply to a different status, do you wish to use it?", preferredStyle: .alert) let alertController = UIAlertController(title: "Different Reply", message: "The selected draft is a reply to a different status, do you wish to use it?", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { (_) in alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { (_) in
completion(false) completion(false)

View File

@ -11,6 +11,8 @@ import Pachyderm
class ComposeStatusReplyView: UIView { class ComposeStatusReplyView: UIView {
weak var mastodonController: MastodonController?
@IBOutlet weak var avatarImageView: UIImageView! @IBOutlet weak var avatarImageView: UIImageView!
@IBOutlet weak var displayNameLabel: UILabel! @IBOutlet weak var displayNameLabel: UILabel!
@IBOutlet weak var usernameLabel: UILabel! @IBOutlet weak var usernameLabel: UILabel!
@ -34,6 +36,7 @@ class ComposeStatusReplyView: UIView {
func updateUI(for status: Status) { func updateUI(for status: Status) {
displayNameLabel.text = status.account.realDisplayName displayNameLabel.text = status.account.realDisplayName
usernameLabel.text = "@\(status.account.acct)" usernameLabel.text = "@\(status.account.acct)"
statusContentTextView.overrideMastodonController = mastodonController
statusContentTextView.statusID = status.id statusContentTextView.statusID = status.id
ImageCache.avatars.get(status.account.avatar) { (data) in ImageCache.avatars.get(status.account.avatar) { (data) in

View File

@ -16,7 +16,8 @@ private let emojiRegex = try! NSRegularExpression(pattern: ":(\\w+):", options:
class ContentTextView: LinkTextView { class ContentTextView: LinkTextView {
weak var navigationDelegate: TuskerNavigationDelegate? weak var navigationDelegate: TuskerNavigationDelegate?
var mastodonController: MastodonController? { navigationDelegate?.apiController } weak var overrideMastodonController: MastodonController?
var mastodonController: MastodonController? { overrideMastodonController ?? navigationDelegate?.apiController }
var defaultFont: UIFont = .systemFont(ofSize: 17) var defaultFont: UIFont = .systemFont(ofSize: 17)
var defaultColor: UIColor = .label var defaultColor: UIColor = .label