Add local source ingest and podcasts

This commit is contained in:
Krishna Kumar
2026-07-02 01:11:03 -05:00
parent 4d875e12d6
commit f8693f4be0
18 changed files with 1044 additions and 31 deletions

View File

@@ -4,6 +4,13 @@ import UniformTypeIdentifiers
@objc(ShareViewController)
class ShareViewController: UIViewController {
private let supportedTypeIdentifiers = [
UTType.url.identifier,
UTType.html.identifier,
UTType.rtf.identifier,
UTType.plainText.identifier,
UTType.text.identifier
]
override func viewDidLoad() {
super.viewDidLoad()
@@ -11,37 +18,49 @@ class ShareViewController: UIViewController {
blur.frame = view.bounds
blur.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(blur)
extractURL()
extractPayload()
}
private func extractURL() {
private func extractPayload() {
guard let item = extensionContext?.inputItems.first as? NSExtensionItem,
let attachments = item.attachments else {
present(url: nil)
present(payload: nil)
return
}
func load(typeId: String) -> Bool {
guard let attachment = attachments.first(where: { $0.hasItemConformingToTypeIdentifier(typeId) }) else {
return false
}
attachment.loadItem(forTypeIdentifier: typeId, options: nil) { [weak self] item, _ in
let urlString = typeId == UTType.url.identifier
? ((item as? URL)?.absoluteString ?? (item as? String))
: (item as? String)
DispatchQueue.main.async { self?.present(url: urlString) }
}
return true
let candidates = attachments.flatMap { attachment in
supportedTypeIdentifiers
.filter { attachment.hasItemConformingToTypeIdentifier($0) }
.map { (attachment, $0) }
}
if !load(typeId: UTType.url.identifier) && !load(typeId: UTType.plainText.identifier) {
present(url: nil)
loadNext(candidates, index: 0)
}
private func loadNext(_ candidates: [(NSItemProvider, String)], index: Int) {
guard index < candidates.count else {
present(payload: nil)
return
}
let (attachment, typeIdentifier) = candidates[index]
attachment.loadItem(forTypeIdentifier: typeIdentifier, options: nil) { [weak self] item, _ in
guard let self else { return }
if let payload = IngestPayloadParser.parse(item: item, typeIdentifier: typeIdentifier) {
DispatchQueue.main.async { self.present(payload: payload) }
} else {
DispatchQueue.main.async { self.loadNext(candidates, index: index + 1) }
}
}
}
/// Hosts the SwiftUI save card. A nil URL surfaces an error state in the card.
private func present(url: String?) {
let root = ShareView(url: url ?? "") { [weak self] _ in
private func present(payload: IngestPayload?) {
let root = ShareView(
url: payload?.url ?? "",
initialTitle: payload?.title,
initialNotes: payload?.notes ?? ""
) { [weak self] _ in
self?.close()
}
let host = UIHostingController(rootView: root)
@@ -52,7 +71,7 @@ class ShareViewController: UIViewController {
view.addSubview(host.view)
host.didMove(toParent: self)
if url == nil {
if payload == nil {
// No URL to work with let the card render its failure state briefly.
DispatchQueue.main.asyncAfter(deadline: .now() + 1.6) { [weak self] in self?.close() }
}