spb/poche Public
Agent personnel 100 % on-device — SwiftUI + Apple Foundation Models + EventKit + SwiftData. Aucune API, aucun serveur.
Swift 100%
1//2// ShareViewController.swift3// PocheShare4//5// Author: Simon-Pierre Boucher6// Contact: contact@spboucher.ai7//89import UIKit10import UniformTypeIdentifiers1112/// Share Extension: entry only (CLAUDE.md §4). The shared text or link is13/// dropped into the app-group inbox; the app imports it as a note on next14/// launch. Nothing leaves the device.15final class ShareViewController: UIViewController {16 override func viewDidLoad() {17 super.viewDidLoad()18 view.backgroundColor = .clear1920 let card = UIVisualEffectView(effect: UIBlurEffect(style: .systemMaterial))21 card.layer.cornerRadius = 2022 card.clipsToBounds = true23 card.translatesAutoresizingMaskIntoConstraints = false2425 let label = UILabel()26 label.text = "Enregistré dans Poche ✓"27 label.font = .systemFont(ofSize: 17, weight: .semibold)28 label.translatesAutoresizingMaskIntoConstraints = false29 card.contentView.addSubview(label)3031 view.addSubview(card)32 NSLayoutConstraint.activate([33 card.centerXAnchor.constraint(equalTo: view.centerXAnchor),34 card.centerYAnchor.constraint(equalTo: view.centerYAnchor),35 label.topAnchor.constraint(equalTo: card.contentView.topAnchor, constant: 18),36 label.bottomAnchor.constraint(equalTo: card.contentView.bottomAnchor, constant: -18),37 label.leadingAnchor.constraint(equalTo: card.contentView.leadingAnchor, constant: 24),38 label.trailingAnchor.constraint(equalTo: card.contentView.trailingAnchor, constant: -24),39 ])40 }4142 override func viewDidAppear(_ animated: Bool) {43 super.viewDidAppear(animated)44 Task {45 await saveSharedContent()46 try? await Task.sleep(for: .seconds(0.8))47 extensionContext?.completeRequest(returningItems: nil)48 }49 }5051 private func saveSharedContent() async {52 guard let items = extensionContext?.inputItems as? [NSExtensionItem] else { return }5354 for item in items {55 for provider in item.attachments ?? [] {56 if provider.hasItemConformingToTypeIdentifier(UTType.plainText.identifier),57 let raw = try? await provider.loadItem(forTypeIdentifier: UTType.plainText.identifier),58 let text = raw as? String {59 save(text: text, fallbackTitle: item.attributedContentText?.string)60 return61 }62 if provider.hasItemConformingToTypeIdentifier(UTType.url.identifier),63 let raw = try? await provider.loadItem(forTypeIdentifier: UTType.url.identifier),64 let url = raw as? URL {65 save(text: url.absoluteString, fallbackTitle: item.attributedContentText?.string)66 return67 }68 }69 }70 }7172 private func save(text: String, fallbackTitle: String?) {73 let firstLine = text74 .components(separatedBy: .newlines)75 .first?76 .trimmingCharacters(in: .whitespaces) ?? "Partage"77 let title = String((fallbackTitle?.isEmpty == false ? fallbackTitle! : firstLine).prefix(80))78 SharedInbox.append(SharedInboxItem(79 title: title,80 content: String(text.prefix(2000)),81 date: .now82 ))83 }84}85