Use LPLinkMetadata to improve sharing behavior

This commit is contained in:
Jed Fox 2022-10-31 16:01:19 -04:00
parent 4a6ab82570
commit ceece731a4
No known key found for this signature in database
GPG Key ID: 0B61D18EA54B47E1
4 changed files with 65 additions and 12 deletions

View File

@ -7,9 +7,13 @@
import UIKit import UIKit
import CoreDataStack import CoreDataStack
import Alamofire
import AlamofireImage
import MastodonCore import MastodonCore
import MastodonUI import MastodonUI
import MastodonLocalization import MastodonLocalization
import LinkPresentation
import UniformTypeIdentifiers
// Delete // Delete
extension DataSourceFacade { extension DataSourceFacade {
@ -56,8 +60,7 @@ extension DataSourceFacade {
) async throws -> UIActivityViewController { ) async throws -> UIActivityViewController {
var activityItems: [Any] = try await dependency.context.managedObjectContext.perform { var activityItems: [Any] = try await dependency.context.managedObjectContext.perform {
guard let status = status.object(in: dependency.context.managedObjectContext) else { return [] } guard let status = status.object(in: dependency.context.managedObjectContext) else { return [] }
let url = status.url ?? status.uri return [StatusActivityItem(status: status)].compactMap { $0 } as [Any]
return [URL(string: url)].compactMap { $0 } as [Any]
} }
var applicationActivities: [UIActivity] = [ var applicationActivities: [UIActivity] = [
SafariActivity(sceneCoordinator: dependency.coordinator), // open URL SafariActivity(sceneCoordinator: dependency.coordinator), // open URL
@ -74,6 +77,54 @@ extension DataSourceFacade {
) )
return activityViewController return activityViewController
} }
private class StatusActivityItem: NSObject, UIActivityItemSource {
init?(status: Status) {
guard let url = URL(string: status.url ?? status.uri) else { return nil }
self.url = url
self.metadata = LPLinkMetadata()
metadata.url = url
metadata.title = "\(status.author.displayName) (@\(status.author.username)@\(status.author.domain))"
metadata.iconProvider = NSItemProvider(object: IconProvider(url: status.author.avatarImageURLWithFallback(domain: status.author.domain)))
}
let url: URL
let metadata: LPLinkMetadata
func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
url
}
func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
url
}
func activityViewControllerLinkMetadata(_ activityViewController: UIActivityViewController) -> LPLinkMetadata? {
metadata
}
private class IconProvider: NSObject, NSItemProviderWriting {
let url: URL
init(url: URL) {
self.url = url
}
static var writableTypeIdentifiersForItemProvider: [String] {
[UTType.png.identifier]
}
func loadData(withTypeIdentifier typeIdentifier: String, forItemProviderCompletionHandler completionHandler: @escaping @Sendable (Data?, Error?) -> Void) -> Progress? {
let filter = ScaledToSizeFilter(size: CGSize.authorAvatarButtonSize)
let receipt = UIImageView.af.sharedImageDownloader.download(URLRequest(url: url), filter: filter, completion: { response in
switch response.result {
case .failure(let error): completionHandler(nil, error)
case .success(let image): completionHandler(image.pngData(), nil)
}
})
return receipt?.request.downloadProgress
}
}
}
} }
// ActionToolBar // ActionToolBar

View File

@ -226,14 +226,13 @@ extension NotificationView {
.store(in: &_disposeBag) .store(in: &_disposeBag)
// avatarButton // avatarButton
let authorAvatarButtonSize = CGSize(width: 46, height: 46) avatarButton.size = CGSize.authorAvatarButtonSize
avatarButton.size = authorAvatarButtonSize avatarButton.avatarImageView.imageViewSize = CGSize.authorAvatarButtonSize
avatarButton.avatarImageView.imageViewSize = authorAvatarButtonSize
avatarButton.translatesAutoresizingMaskIntoConstraints = false avatarButton.translatesAutoresizingMaskIntoConstraints = false
authorContainerView.addArrangedSubview(avatarButton) authorContainerView.addArrangedSubview(avatarButton)
NSLayoutConstraint.activate([ NSLayoutConstraint.activate([
avatarButton.widthAnchor.constraint(equalToConstant: authorAvatarButtonSize.width).priority(.required - 1), avatarButton.widthAnchor.constraint(equalToConstant: CGSize.authorAvatarButtonSize.width).priority(.required - 1),
avatarButton.heightAnchor.constraint(equalToConstant: authorAvatarButtonSize.height).priority(.required - 1), avatarButton.heightAnchor.constraint(equalToConstant: CGSize.authorAvatarButtonSize.height).priority(.required - 1),
]) ])
avatarButton.setContentHuggingPriority(.required - 1, for: .vertical) avatarButton.setContentHuggingPriority(.required - 1, for: .vertical)
avatarButton.setContentCompressionResistancePriority(.required - 1, for: .vertical) avatarButton.setContentCompressionResistancePriority(.required - 1, for: .vertical)

View File

@ -210,14 +210,13 @@ extension StatusAuthorView {
// author container: H - [ avatarButton | authorMetaContainer ] // author container: H - [ avatarButton | authorMetaContainer ]
private func layoutBase() { private func layoutBase() {
// avatarButton // avatarButton
let authorAvatarButtonSize = CGSize(width: 46, height: 46) avatarButton.size = CGSize.authorAvatarButtonSize
avatarButton.size = authorAvatarButtonSize avatarButton.avatarImageView.imageViewSize = CGSize.authorAvatarButtonSize
avatarButton.avatarImageView.imageViewSize = authorAvatarButtonSize
avatarButton.translatesAutoresizingMaskIntoConstraints = false avatarButton.translatesAutoresizingMaskIntoConstraints = false
addArrangedSubview(avatarButton) addArrangedSubview(avatarButton)
NSLayoutConstraint.activate([ NSLayoutConstraint.activate([
avatarButton.widthAnchor.constraint(equalToConstant: authorAvatarButtonSize.width).priority(.required - 1), avatarButton.widthAnchor.constraint(equalToConstant: CGSize.authorAvatarButtonSize.width).priority(.required - 1),
avatarButton.heightAnchor.constraint(equalToConstant: authorAvatarButtonSize.height).priority(.required - 1), avatarButton.heightAnchor.constraint(equalToConstant: CGSize.authorAvatarButtonSize.height).priority(.required - 1),
]) ])
avatarButton.setContentHuggingPriority(.required - 1, for: .vertical) avatarButton.setContentHuggingPriority(.required - 1, for: .vertical)
avatarButton.setContentCompressionResistancePriority(.required - 1, for: .vertical) avatarButton.setContentCompressionResistancePriority(.required - 1, for: .vertical)

View File

@ -14,6 +14,10 @@ import MastodonAsset
import MastodonCore import MastodonCore
import MastodonLocalization import MastodonLocalization
public extension CGSize {
static let authorAvatarButtonSize = CGSize(width: 46, height: 46)
}
public protocol StatusViewDelegate: AnyObject { public protocol StatusViewDelegate: AnyObject {
func statusView(_ statusView: StatusView, headerDidPressed header: UIView) func statusView(_ statusView: StatusView, headerDidPressed header: UIView)
func statusView(_ statusView: StatusView, authorAvatarButtonDidPressed button: AvatarButton) func statusView(_ statusView: StatusView, authorAvatarButtonDidPressed button: AvatarButton)