SPB Git

spb/poche Public

Agent personnel 100 % on-device — SwiftUI + Apple Foundation Models + EventKit + SwiftData. Aucune API, aucun serveur.

Swift 100%
3.3 KB · 85 lines swift
Raw Blame History
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