feat(ios): share extension ile Ratebubble iOS istemcisini ekle ve paylaşım akışını düzelt
This commit is contained in:
107
ios/Ratebubble/ShareExtension/ShareViewController.swift
Normal file
107
ios/Ratebubble/ShareExtension/ShareViewController.swift
Normal file
@@ -0,0 +1,107 @@
|
||||
import UIKit
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
final class ShareViewController: UIViewController {
|
||||
private let statusLabel = UILabel()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
setupUI()
|
||||
Task { await handleIncomingShare() }
|
||||
}
|
||||
|
||||
private func setupUI() {
|
||||
view.backgroundColor = .systemBackground
|
||||
statusLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||
statusLabel.textAlignment = .center
|
||||
statusLabel.numberOfLines = 0
|
||||
statusLabel.text = "Paylaşılan bağlantı alınıyor..."
|
||||
|
||||
view.addSubview(statusLabel)
|
||||
NSLayoutConstraint.activate([
|
||||
statusLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
|
||||
statusLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
|
||||
statusLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor)
|
||||
])
|
||||
}
|
||||
|
||||
@MainActor
|
||||
private func updateStatus(_ text: String) {
|
||||
statusLabel.text = text
|
||||
}
|
||||
|
||||
private func handleIncomingShare() async {
|
||||
guard let item = extensionContext?.inputItems.first as? NSExtensionItem,
|
||||
let providers = item.attachments else {
|
||||
updateStatus("Paylaşılan içerik okunamadı.")
|
||||
return
|
||||
}
|
||||
|
||||
for provider in providers {
|
||||
if let extracted = await extractURL(from: provider), isSupportedStreamingURL(extracted) {
|
||||
SharedPayloadStore.saveIncomingURL(extracted.absoluteString)
|
||||
updateStatus("Bağlantı alındı, uygulama açılıyor...")
|
||||
openHostApp()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
updateStatus("Geçerli bir Netflix/Prime Video linki bulunamadı.")
|
||||
}
|
||||
|
||||
private func extractURL(from provider: NSItemProvider) async -> URL? {
|
||||
if provider.hasItemConformingToTypeIdentifier(UTType.url.identifier) {
|
||||
return await withCheckedContinuation { continuation in
|
||||
provider.loadItem(forTypeIdentifier: UTType.url.identifier, options: nil) { item, _ in
|
||||
continuation.resume(returning: item as? URL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if provider.hasItemConformingToTypeIdentifier(UTType.text.identifier) {
|
||||
return await withCheckedContinuation { continuation in
|
||||
provider.loadItem(forTypeIdentifier: UTType.text.identifier, options: nil) { item, _ in
|
||||
if let raw = item as? String, let url = URL(string: raw.trimmingCharacters(in: .whitespacesAndNewlines)) {
|
||||
continuation.resume(returning: url)
|
||||
return
|
||||
}
|
||||
continuation.resume(returning: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
private func isSupportedStreamingURL(_ url: URL) -> Bool {
|
||||
let host = url.host?.lowercased() ?? ""
|
||||
let netflixHosts = ["www.netflix.com", "netflix.com", "www.netflix.com.tr", "netflix.com.tr"]
|
||||
let primeHosts = ["www.primevideo.com", "primevideo.com", "www.amazon.com", "amazon.com"]
|
||||
|
||||
let isNetflix = netflixHosts.contains(host)
|
||||
let isPrime = primeHosts.contains(host)
|
||||
guard isNetflix || isPrime else { return false }
|
||||
|
||||
let path = url.path.lowercased()
|
||||
if path.contains("/title/") || path.contains("/watch/") || path.contains("/detail/") {
|
||||
return true
|
||||
}
|
||||
|
||||
// Some share links can be shortened/redirect style without a canonical path.
|
||||
return !path.isEmpty && path != "/"
|
||||
}
|
||||
|
||||
private func openHostApp() {
|
||||
guard let url = URL(string: "\(SharedConfig.appURLScheme)://ingest") else {
|
||||
extensionContext?.completeRequest(returningItems: nil)
|
||||
return
|
||||
}
|
||||
|
||||
extensionContext?.open(url) { success in
|
||||
// If opening succeeded, the system should transition to the host app.
|
||||
// Completing the extension request immediately can bounce back to the source app.
|
||||
guard !success else { return }
|
||||
self.extensionContext?.completeRequest(returningItems: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user