Compare commits

..

No commits in common. "14e8c11f02f872a72bd911d976425f1bf9365cd9" and "4719342a06ec4af6d673861a982a3f1a502d8916" have entirely different histories.

7 changed files with 22 additions and 67 deletions

View File

@ -1,12 +1,5 @@
# Changelog # Changelog
## 2020.1 (10)
This build is a hotfix for a couple pressing issues. The changelog for the previous build is included below.
Bugfixes:
- Fix crash when opening Preferences while signed in with a deleted account
- Fix visibility and content warning not being copied when replying to a post
## 2020.1 (9) ## 2020.1 (9)
The marquee feature of this build is the new and improved Compose screen. It's been rewritten to use SwiftUI, is significantly more resilient to data loss, and now shows the toolbar when the main text field is not focused. It also turns out Apple is surprise-releasing iOS 14 very soon (or possibly already has, depending when you're reading this). For those who were not already on the beta train, iOS 14 brings a number of new features including a sidebar on iPadOS and lots and lots of context menus (a home screen widget is coming Soon™). The marquee feature of this build is the new and improved Compose screen. It's been rewritten to use SwiftUI, is significantly more resilient to data loss, and now shows the toolbar when the main text field is not focused. It also turns out Apple is surprise-releasing iOS 14 very soon (or possibly already has, depending when you're reading this). For those who were not already on the beta train, iOS 14 brings a number of new features including a sidebar on iPadOS and lots and lots of context menus (a home screen widget is coming Soon™).

View File

@ -2229,7 +2229,7 @@
CODE_SIGN_ENTITLEMENTS = Tusker/Tusker.entitlements; CODE_SIGN_ENTITLEMENTS = Tusker/Tusker.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 10; CURRENT_PROJECT_VERSION = 9;
DEVELOPMENT_TEAM = V4WK9KR9U2; DEVELOPMENT_TEAM = V4WK9KR9U2;
INFOPLIST_FILE = Tusker/Info.plist; INFOPLIST_FILE = Tusker/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.4; IPHONEOS_DEPLOYMENT_TARGET = 13.4;
@ -2258,7 +2258,7 @@
CODE_SIGN_ENTITLEMENTS = Tusker/Tusker.entitlements; CODE_SIGN_ENTITLEMENTS = Tusker/Tusker.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 10; CURRENT_PROJECT_VERSION = 9;
DEVELOPMENT_TEAM = V4WK9KR9U2; DEVELOPMENT_TEAM = V4WK9KR9U2;
INFOPLIST_FILE = Tusker/Info.plist; INFOPLIST_FILE = Tusker/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.4; IPHONEOS_DEPLOYMENT_TARGET = 13.4;

View File

@ -84,28 +84,23 @@ class MastodonController {
} }
} }
func getOwnAccount(completion: ((Result<Account, Client.Error>) -> Void)? = nil) { func getOwnAccount(completion: ((Account) -> Void)? = nil) {
if account != nil { if account != nil {
completion?(.success(account)) completion?(account)
} else { } else {
let request = Client.getSelfAccount() let request = Client.getSelfAccount()
run(request) { response in run(request) { response in
switch response { guard case let .success(account, _) = response else { fatalError() }
case let .failure(error): self.account = account
completion?(.failure(error)) self.persistentContainer.backgroundContext.perform {
if let accountMO = self.persistentContainer.account(for: account.id, in: self.persistentContainer.backgroundContext) {
case let .success(account, _): accountMO.updateFrom(apiAccount: account, container: self.persistentContainer)
self.account = account } else {
self.persistentContainer.backgroundContext.perform { // the first time the user's account is added to the store,
if let accountMO = self.persistentContainer.account(for: account.id, in: self.persistentContainer.backgroundContext) { // increment its reference count so that it's never removed
accountMO.updateFrom(apiAccount: account, container: self.persistentContainer) self.persistentContainer.addOrUpdate(account: account, incrementReferenceCount: true)
} else {
// the first time the user's account is added to the store,
// increment its reference count so that it's never removed
self.persistentContainer.addOrUpdate(account: account, incrementReferenceCount: true)
}
completion?(.success(account))
} }
completion?(account)
} }
} }
} }

View File

@ -119,29 +119,10 @@ extension MastodonController {
func createDraft(inReplyToID: String? = nil, mentioningAcct: String? = nil) -> Draft { func createDraft(inReplyToID: String? = nil, mentioningAcct: String? = nil) -> Draft {
var acctsToMention = [String]() var acctsToMention = [String]()
var visibility = Preferences.shared.defaultPostVisibility
var contentWarning = ""
if let inReplyToID = inReplyToID, if let inReplyToID = inReplyToID,
let inReplyTo = persistentContainer.status(for: inReplyToID) { let inReplyTo = persistentContainer.status(for: inReplyToID) {
acctsToMention.append(inReplyTo.account.acct) acctsToMention.append(inReplyTo.account.acct)
acctsToMention.append(contentsOf: inReplyTo.mentions.map(\.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 { if let mentioningAcct = mentioningAcct {
acctsToMention.append(mentioningAcct) acctsToMention.append(mentioningAcct)
@ -155,9 +136,6 @@ extension MastodonController {
draft.inReplyToID = inReplyToID draft.inReplyToID = inReplyToID
draft.text = acctsToMention.map { "@\($0) " }.joined() draft.text = acctsToMention.map { "@\($0) " }.joined()
draft.initialText = draft.text draft.initialText = draft.text
draft.visibility = visibility
draft.contentWarning = contentWarning
draft.contentWarningEnabled = !contentWarning.isEmpty
return draft return draft
} }

View File

@ -70,21 +70,13 @@ extension OnboardingViewController: InstanceSelectorTableViewControllerDelegate
let tempAccountInfo = LocalData.UserAccountInfo(id: "temp", instanceURL: instanceURL, clientID: clientID, clientSecret: clientSecret, username: nil, accessToken: accessToken) let tempAccountInfo = LocalData.UserAccountInfo(id: "temp", instanceURL: instanceURL, clientID: clientID, clientSecret: clientSecret, username: nil, accessToken: accessToken)
mastodonController.accountInfo = tempAccountInfo mastodonController.accountInfo = tempAccountInfo
mastodonController.getOwnAccount { (result) in mastodonController.getOwnAccount { (account) in
DispatchQueue.main.async { DispatchQueue.main.async {
switch result { // this needs to happen on the main thread because it publishes a new value for the ObservableObject
case let .failure(error): let accountInfo = LocalData.shared.addAccount(instanceURL: instanceURL, clientID: clientID, clientSecret: clientSecret, username: account.username, accessToken: accessToken)
let alert = UIAlertController(title: "Unable to Verify Credentials", message: "Your account could not be fetched at this time: \(error.localizedDescription)", preferredStyle: .alert) mastodonController.accountInfo = accountInfo
alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: nil))
self.present(alert, animated: true)
case let .success(account): self.onboardingDelegate?.didFinishOnboarding(account: accountInfo)
// this needs to happen on the main thread because it publishes a new value for the ObservableObject
let accountInfo = LocalData.shared.addAccount(instanceURL: instanceURL, clientID: clientID, clientSecret: clientSecret, username: account.username, accessToken: accessToken)
mastodonController.accountInfo = accountInfo
self.onboardingDelegate?.didFinishOnboarding(account: accountInfo)
}
} }
} }
} }

View File

@ -36,8 +36,7 @@ struct LocalAccountAvatarView: View {
func loadImage() { func loadImage() {
let controller = MastodonController.getForAccount(localAccountInfo) let controller = MastodonController.getForAccount(localAccountInfo)
controller.getOwnAccount { (result) in controller.getOwnAccount { (account) in
guard case let .success(account) = result else { return }
_ = ImageCache.avatars.get(account.avatar) { (data) in _ = ImageCache.avatars.get(account.avatar) { (data) in
if let data = data, let image = UIImage(data: data) { if let data = data, let image = UIImage(data: data) {
DispatchQueue.main.async { DispatchQueue.main.async {

View File

@ -16,9 +16,7 @@ class MyProfileViewController: ProfileViewController {
title = "My Profile" title = "My Profile"
tabBarItem.image = UIImage(systemName: "person.fill") tabBarItem.image = UIImage(systemName: "person.fill")
mastodonController.getOwnAccount { (result) in mastodonController.getOwnAccount { (account) in
guard case let .success(account) = result else { return }
DispatchQueue.main.async { DispatchQueue.main.async {
self.accountID = account.id self.accountID = account.id
} }