Show share sheet with custom activities instead of alert controller for account actions

This commit is contained in:
Shadowfacts 2019-09-05 12:49:17 -04:00
parent 6a09c7e1e8
commit b60688f4b8
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
8 changed files with 277 additions and 35 deletions

View File

@ -148,6 +148,12 @@
D68632AC21ED8319008C716E /* GMImagePicker.strings in Resources */ = {isa = PBXBuildFile; fileRef = D686329321ED8319008C716E /* GMImagePicker.strings */; };
D6A5FAF1217B7E05003DB2D9 /* ComposeViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6A5FAF0217B7E05003DB2D9 /* ComposeViewController.xib */; };
D6A5FAFB217B86CE003DB2D9 /* OnboardingViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6A5FAFA217B86CE003DB2D9 /* OnboardingViewController.xib */; };
D6AEBB3E2321638100E5038B /* UIActivity+Types.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6AEBB3D2321638100E5038B /* UIActivity+Types.swift */; };
D6AEBB412321642700E5038B /* SendMesasgeActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6AEBB402321642700E5038B /* SendMesasgeActivity.swift */; };
D6AEBB432321685E00E5038B /* OpenInSafariActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6AEBB422321685E00E5038B /* OpenInSafariActivity.swift */; };
D6AEBB4523216AF800E5038B /* FollowAccountActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6AEBB4423216AF800E5038B /* FollowAccountActivity.swift */; };
D6AEBB4823216B1D00E5038B /* AccountActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6AEBB4723216B1D00E5038B /* AccountActivity.swift */; };
D6AEBB4A23216F0400E5038B /* UnfollowAccountActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6AEBB4923216F0400E5038B /* UnfollowAccountActivity.swift */; };
D6B8DB342182A59300424AF7 /* UIAlertController+Visibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6B8DB332182A59300424AF7 /* UIAlertController+Visibility.swift */; };
D6BC874521961F73006163F1 /* Gifu.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6BC874421961F73006163F1 /* Gifu.framework */; };
D6BC874621961F73006163F1 /* Gifu.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D6BC874421961F73006163F1 /* Gifu.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
@ -382,6 +388,12 @@
D686329421ED8319008C716E /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = GMImagePicker.strings; sourceTree = "<group>"; };
D6A5FAF0217B7E05003DB2D9 /* ComposeViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ComposeViewController.xib; sourceTree = "<group>"; };
D6A5FAFA217B86CE003DB2D9 /* OnboardingViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = OnboardingViewController.xib; sourceTree = "<group>"; };
D6AEBB3D2321638100E5038B /* UIActivity+Types.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIActivity+Types.swift"; sourceTree = "<group>"; };
D6AEBB402321642700E5038B /* SendMesasgeActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendMesasgeActivity.swift; sourceTree = "<group>"; };
D6AEBB422321685E00E5038B /* OpenInSafariActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenInSafariActivity.swift; sourceTree = "<group>"; };
D6AEBB4423216AF800E5038B /* FollowAccountActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowAccountActivity.swift; sourceTree = "<group>"; };
D6AEBB4723216B1D00E5038B /* AccountActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountActivity.swift; sourceTree = "<group>"; };
D6AEBB4923216F0400E5038B /* UnfollowAccountActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnfollowAccountActivity.swift; sourceTree = "<group>"; };
D6B8DB332182A59300424AF7 /* UIAlertController+Visibility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIAlertController+Visibility.swift"; sourceTree = "<group>"; };
D6BC874421961F73006163F1 /* Gifu.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Gifu.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D6BC8747219738E1006163F1 /* EnhancedTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnhancedTableViewController.swift; sourceTree = "<group>"; };
@ -918,6 +930,27 @@
path = de.lproj;
sourceTree = "<group>";
};
D6AEBB3F2321640F00E5038B /* Activities */ = {
isa = PBXGroup;
children = (
D6AEBB3D2321638100E5038B /* UIActivity+Types.swift */,
D6AEBB4623216B0C00E5038B /* Account Activities */,
D6AEBB422321685E00E5038B /* OpenInSafariActivity.swift */,
);
path = Activities;
sourceTree = "<group>";
};
D6AEBB4623216B0C00E5038B /* Account Activities */ = {
isa = PBXGroup;
children = (
D6AEBB4723216B1D00E5038B /* AccountActivity.swift */,
D6AEBB402321642700E5038B /* SendMesasgeActivity.swift */,
D6AEBB4423216AF800E5038B /* FollowAccountActivity.swift */,
D6AEBB4923216F0400E5038B /* UnfollowAccountActivity.swift */,
);
path = "Account Activities";
sourceTree = "<group>";
};
D6BED1722126661300F02DA0 /* Views */ = {
isa = PBXGroup;
children = (
@ -1001,6 +1034,7 @@
D6757A7A2157E00100721E32 /* XCallbackURL */,
D62D241E217AA46B005076CC /* Shortcuts */,
D663626021360A9600C9CBA2 /* Preferences */,
D6AEBB3F2321640F00E5038B /* Activities */,
D667E5F62135C2ED0057A976 /* Extensions */,
D6F953F121251A2F00CF0F2B /* Controllers */,
D641C780213DD7C4004B4513 /* Screens */,
@ -1403,6 +1437,7 @@
0427033A22B31269000D31B6 /* AdvancedPrefsView.swift in Sources */,
D6757A822157E8FA00721E32 /* XCBSession.swift in Sources */,
04DACE8C212CB14B009840C4 /* MainTabBarViewController.swift in Sources */,
D6AEBB412321642700E5038B /* SendMesasgeActivity.swift in Sources */,
D6C693F92162E4DB007D6A6D /* StatusContentLabel.swift in Sources */,
D6D58DF922074B74009C8DD9 /* LinkLabel.swift in Sources */,
0454DDAF22B462EF00B8BB8E /* GalleryExpandAnimationController.swift in Sources */,
@ -1423,12 +1458,15 @@
D67C57B421E2910700C3118B /* ComposeStatusReplyView.swift in Sources */,
04DACE8E212CC7CC009840C4 /* ImageCache.swift in Sources */,
D627FF7B217E951500CC0648 /* DraftsTableViewController.swift in Sources */,
D6AEBB4823216B1D00E5038B /* AccountActivity.swift in Sources */,
D6333B772138D94E00CE884A /* ComposeMediaView.swift in Sources */,
04ED00B121481ED800567C53 /* SteppedProgressView.swift in Sources */,
D627FF7F217E95E000CC0648 /* DraftTableViewCell.swift in Sources */,
D6AEBB4A23216F0400E5038B /* UnfollowAccountActivity.swift in Sources */,
D663626421360D2300C9CBA2 /* AvatarStyle.swift in Sources */,
D679C09F215850EF00DA27FE /* XCBActions.swift in Sources */,
D6DD353F22F502EC00A9563A /* Preferences+Notification.swift in Sources */,
D6AEBB4523216AF800E5038B /* FollowAccountActivity.swift in Sources */,
D6538945214D6D7500E3CEFC /* TableViewSwipeActionProvider.swift in Sources */,
D6E0DC8E216EDF1E00369478 /* Previewing.swift in Sources */,
D6BED174212667E900F02DA0 /* StatusTableViewCell.swift in Sources */,
@ -1448,6 +1486,7 @@
D6B8DB342182A59300424AF7 /* UIAlertController+Visibility.swift in Sources */,
D67C57AD21E265FC00C3118B /* LargeAccountDetailView.swift in Sources */,
D641C777213CAA9E004B4513 /* ActionNotificationTableViewCell.swift in Sources */,
D6AEBB432321685E00E5038B /* OpenInSafariActivity.swift in Sources */,
D6C693FE2162FEEA007D6A6D /* UIViewController+Children.swift in Sources */,
D64D0AB12128D9AE005A6F37 /* OnboardingViewController.swift in Sources */,
D627FF76217E923E00CC0648 /* DraftsManager.swift in Sources */,
@ -1466,6 +1505,7 @@
D6757A7C2157E01900721E32 /* XCBManager.swift in Sources */,
D6F1F84D2193B56E00F5FE67 /* Cache.swift in Sources */,
0427037C22B316B9000D31B6 /* SilentActionPrefs.swift in Sources */,
D6AEBB3E2321638100E5038B /* UIActivity+Types.swift in Sources */,
D6757A7E2157E02600721E32 /* XCBRequestSpec.swift in Sources */,
D667E5F12134D5050057A976 /* UIViewController+Delegates.swift in Sources */,
D6BC8748219738E1006163F1 /* EnhancedTableViewController.swift in Sources */,

View File

@ -0,0 +1,34 @@
//
// AccountActivity.swift
// Tusker
//
// Created by Shadowfacts on 9/5/19.
// Copyright © 2019 Shadowfacts. All rights reserved.
//
import UIKit
import Pachyderm
class AccountActivity: UIActivity {
override class var activityCategory: UIActivity.Category {
return .action
}
var account: Account?
override func canPerform(withActivityItems activityItems: [Any]) -> Bool {
for case is Account in activityItems {
return true
}
return false
}
override func prepare(withActivityItems activityItems: [Any]) {
for case let account as Account in activityItems {
self.account = account
return
}
}
}

View File

@ -0,0 +1,42 @@
//
// FollowAccountActivity.swift
// Tusker
//
// Created by Shadowfacts on 9/5/19.
// Copyright © 2019 Shadowfacts. All rights reserved.
//
import UIKit
import Pachyderm
class FollowAccountActivity: AccountActivity {
override var activityType: UIActivity.ActivityType? {
return .followAccount
}
override var activityTitle: String? {
return NSLocalizedString("Follow", comment: "follow account activity title")
}
override var activityImage: UIImage? {
return UIImage(systemName: "person.badge.plus")
}
override func perform() {
guard let account = account else { return }
UIImpactFeedbackGenerator(style: .medium).impactOccurred()
let request = Account.follow(account.id)
MastodonController.client.run(request) { (response) in
if case let .success(relationship, _) = response {
MastodonCache.add(relationship: relationship)
} else {
// todo: display error message
UINotificationFeedbackGenerator().notificationOccurred(.error)
fatalError()
}
}
}
}

View File

@ -0,0 +1,34 @@
//
// SendMesasgeActivity.swift
// Tusker
//
// Created by Shadowfacts on 9/5/19.
// Copyright © 2019 Shadowfacts. All rights reserved.
//
import UIKit
class SendMessageActivity: AccountActivity {
override var activityType: UIActivity.ActivityType? {
return .sendMessageMentioningAccount
}
override var activityTitle: String? {
return NSLocalizedString("Send Message", comment: "send message activity title")
}
override var activityImage: UIImage? {
return UIImage(systemName: "square.and.pencil")
}
override func perform() {
activityDidFinish(true)
}
override var activityViewController: UIViewController? {
guard let account = account else { return nil }
return UINavigationController(rootViewController: ComposeViewController(mentioningAcct: account.acct))
}
}

View File

@ -0,0 +1,42 @@
//
// UnfollowActivity.swift
// Tusker
//
// Created by Shadowfacts on 9/5/19.
// Copyright © 2019 Shadowfacts. All rights reserved.
//
import UIKit
import Pachyderm
class UnfollowAccountActivity: AccountActivity {
override var activityType: UIActivity.ActivityType? {
return .unfollowAccount
}
override var activityTitle: String? {
return NSLocalizedString("Unfollow", comment: "unfollow account activity title")
}
override var activityImage: UIImage? {
return UIImage(systemName: "person.badge.minus")
}
override func perform() {
guard let account = account else { return }
UIImpactFeedbackGenerator(style: .medium).impactOccurred()
let request = Account.unfollow(account.id)
MastodonController.client.run(request) { (response) in
if case let .success(relationship, _) = response {
MastodonCache.add(relationship: relationship)
} else {
// todo: display error message
UINotificationFeedbackGenerator().notificationOccurred(.error)
fatalError()
}
}
}
}

View File

@ -0,0 +1,47 @@
//
// OpenInSafariActivity.swift
// Tusker
//
// Created by Shadowfacts on 9/5/19.
// Copyright © 2019 Shadowfacts. All rights reserved.
//
import UIKit
import SafariServices
class OpenInSafariActivity: UIActivity {
override class var activityCategory: UIActivity.Category {
return .action
}
override var activityType: UIActivity.ActivityType? {
return .openInSafari
}
override var activityTitle: String? {
return NSLocalizedString("Open in Safari", comment: "open in safari activity title")
}
override var activityImage: UIImage? {
return UIImage(systemName: "safari")
}
override func canPerform(withActivityItems activityItems: [Any]) -> Bool {
for case is URL in activityItems {
return true
}
return false
}
override func perform() {
activityDidFinish(true)
}
static func completionHandler(viewController: UIViewController, url: URL) -> UIActivityViewController.CompletionWithItemsHandler {
return { (activityType, _, _, _) in
if activityType == .openInSafari {
viewController.present(SFSafariViewController(url: url), animated: true)
}
}
}
}

View File

@ -0,0 +1,18 @@
//
// UIActivity+Types.swift
// Tusker
//
// Created by Shadowfacts on 9/5/19.
// Copyright © 2019 Shadowfacts. All rights reserved.
//
import UIKit
extension UIActivity.ActivityType {
static let openInSafari = UIActivity.ActivityType("\(Bundle.main.bundleIdentifier!).open_in_safari")
static let sendMessageMentioningAccount = UIActivity.ActivityType("\(Bundle.main.bundleIdentifier!).send_message_mentioning_account")
static let followAccount = UIActivity.ActivityType("\(Bundle.main.bundleIdentifier!).follow_account")
static let unfollowAccount = UIActivity.ActivityType("\(Bundle.main.bundleIdentifier!).unfollow_account")
}

View File

@ -230,43 +230,28 @@ extension ProfileTableViewController: ProfileHeaderTableViewCellDelegate {
func showMoreOptions() {
let account = MastodonCache.account(for: accountID)!
let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
alert.addAction(UIAlertAction(title: "Open in Safari", style: .default, handler: { _ in
let vc = SFSafariViewController(url: account.url)
self.present(vc, animated: true)
}))
alert.addAction(UIAlertAction(title: "Share", style: .default, handler: { _ in
let vc = UIActivityViewController(activityItems: [account.url], applicationActivities: nil)
self.present(vc, animated: true)
}))
alert.addAction(UIAlertAction(title: "Send Message", style: .default, handler: { _ in
self.sendMessageMentioning()
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
MastodonCache.relationship(for: account.id) { (relationship) in
guard let relationship = relationship else {
DispatchQueue.main.async {
self.present(alert, animated: true)
}
return
MastodonCache.relationship(for: account.id) { [weak self] (relationship) in
guard let self = self else { return }
let customActivities: [UIActivity]
if let relationship = relationship {
let toggleFollowActivity = relationship.following ? UnfollowAccountActivity() : FollowAccountActivity()
customActivities = [
SendMessageActivity(),
toggleFollowActivity,
OpenInSafariActivity()
]
} else {
customActivities = [
SendMessageActivity(),
OpenInSafariActivity()
]
}
let title = relationship.following ? "Unfollow": "Follow"
DispatchQueue.main.async {
alert.addAction(UIAlertAction(title: title, style: .default, handler: { (_) in
UIImpactFeedbackGenerator(style: .medium).impactOccurred()
let request = (relationship.following ? Account.unfollow : Account.follow)(account.id)
MastodonController.client.run(request, completion: { (response) in
if case let .success(relationship, _) = response {
MastodonCache.add(relationship: relationship)
} else {
// todo: display error message
UINotificationFeedbackGenerator().notificationOccurred(.error)
fatalError()
}
})
}))
self.present(alert, animated: true)
let activityController = UIActivityViewController(activityItems: [account.url, account], applicationActivities: customActivities)
activityController.completionWithItemsHandler = OpenInSafariActivity.completionHandler(viewController: self, url: account.url)
self.present(activityController, animated: true)
}
}
}