@swiftbrowser/swift 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Package.swift +214 -0
- package/README.md +10 -2
- package/Sources/AVFoundation/AVFoundation.swift +131 -0
- package/Sources/AVFoundation/Asset.swift +487 -0
- package/Sources/AVFoundation/AudioSession.swift +144 -0
- package/Sources/AVFoundation/CMTime.swift +303 -0
- package/Sources/AVFoundation/Capture.swift +688 -0
- package/Sources/AVFoundation/Player.swift +749 -0
- package/Sources/AVFoundation/PlayerView.swift +117 -0
- package/Sources/AVKit/AVKit.swift +132 -0
- package/Sources/Accelerate/Accelerate.swift +122 -0
- package/Sources/AppIntents/AppIntents.swift +144 -0
- package/Sources/AppIntents/Parameters.swift +220 -0
- package/Sources/AppIntents/Shortcuts.swift +159 -0
- package/Sources/AudioToolbox/AudioToolbox.swift +55 -0
- package/Sources/AuthenticationServices/AuthenticationServices.swift +257 -0
- package/Sources/AuthenticationServices/Authorization.swift +251 -0
- package/Sources/Charts/Charts.swift +61 -0
- package/Sources/Combine/AnyCancellable.swift +65 -0
- package/Sources/Combine/AnyPublisher.swift +148 -0
- package/Sources/Combine/AnySubscriber.swift +230 -0
- package/Sources/Combine/Cancellable.swift +35 -0
- package/Sources/Combine/Codable.swift +29 -0
- package/Sources/Combine/CombineIdentifier.swift +45 -0
- package/Sources/Combine/Concurrency/ConcurrencyHelpers.swift +24 -0
- package/Sources/Combine/Concurrency/Future+Concurrency.swift +136 -0
- package/Sources/Combine/Concurrency/GENERATED-Publisher+Concurrency.swift +397 -0
- package/Sources/Combine/CurrentValueSubject.swift +252 -0
- package/Sources/Combine/CustomCombineIdentifierConvertible.swift +28 -0
- package/Sources/Combine/Future.swift +228 -0
- package/Sources/Combine/GENERATED-RootProtocols.swift +426 -0
- package/Sources/Combine/Helpers/ConduitBase.swift +40 -0
- package/Sources/Combine/Helpers/ConduitList.swift +59 -0
- package/Sources/Combine/Helpers/DebugHook.swift +177 -0
- package/Sources/Combine/Helpers/FilterProducer.swift +174 -0
- package/Sources/Combine/Helpers/Locking.swift +30 -0
- package/Sources/Combine/Helpers/PartialCompletion.swift +26 -0
- package/Sources/Combine/Helpers/ReduceProducer.swift +249 -0
- package/Sources/Combine/Helpers/SubjectSubscriber.swift +96 -0
- package/Sources/Combine/Helpers/SubscriberTap.swift +69 -0
- package/Sources/Combine/Helpers/SubscriptionStatus.swift +33 -0
- package/Sources/Combine/Helpers/SubscriptionTap.swift +33 -0
- package/Sources/Combine/Helpers/Utils.swift +30 -0
- package/Sources/Combine/Helpers/Violations.swift +33 -0
- package/Sources/Combine/ImmediateScheduler.swift +178 -0
- package/Sources/Combine/LICENSE +21 -0
- package/Sources/Combine/NotificationPublisher.swift +48 -0
- package/Sources/Combine/ObjectWillChange.swift +46 -0
- package/Sources/Combine/PassthroughSubject.swift +222 -0
- package/Sources/Combine/Publisher+Subscribe.swift +53 -0
- package/Sources/Combine/Publishers/Deferred.swift +48 -0
- package/Sources/Combine/Publishers/Empty.swift +54 -0
- package/Sources/Combine/Publishers/Fail.swift +42 -0
- package/Sources/Combine/Publishers/GENERATED-Publishers.Catch.swift +673 -0
- package/Sources/Combine/Publishers/GENERATED-Publishers.Encode.swift +388 -0
- package/Sources/Combine/Publishers/GENERATED-Publishers.MapKeyPath.swift +384 -0
- package/Sources/Combine/Publishers/Just.swift +313 -0
- package/Sources/Combine/Publishers/Optional.Publisher.swift +315 -0
- package/Sources/Combine/Publishers/Publishers.AllSatisfy.swift +217 -0
- package/Sources/Combine/Publishers/Publishers.AssertNoFailure.swift +158 -0
- package/Sources/Combine/Publishers/Publishers.Autoconnect.swift +193 -0
- package/Sources/Combine/Publishers/Publishers.Breakpoint.swift +231 -0
- package/Sources/Combine/Publishers/Publishers.Buffer.swift +356 -0
- package/Sources/Combine/Publishers/Publishers.Collect.swift +102 -0
- package/Sources/Combine/Publishers/Publishers.CollectByCount.swift +195 -0
- package/Sources/Combine/Publishers/Publishers.CompactMap.swift +241 -0
- package/Sources/Combine/Publishers/Publishers.Comparison.swift +371 -0
- package/Sources/Combine/Publishers/Publishers.Concatenate.swift +474 -0
- package/Sources/Combine/Publishers/Publishers.Contains.swift +293 -0
- package/Sources/Combine/Publishers/Publishers.Count.swift +87 -0
- package/Sources/Combine/Publishers/Publishers.Debounce.swift +332 -0
- package/Sources/Combine/Publishers/Publishers.Delay.swift +269 -0
- package/Sources/Combine/Publishers/Publishers.Drop.swift +155 -0
- package/Sources/Combine/Publishers/Publishers.DropUntilOutput.swift +283 -0
- package/Sources/Combine/Publishers/Publishers.DropWhile.swift +378 -0
- package/Sources/Combine/Publishers/Publishers.Filter.swift +248 -0
- package/Sources/Combine/Publishers/Publishers.First.swift +261 -0
- package/Sources/Combine/Publishers/Publishers.FlatMap.swift +533 -0
- package/Sources/Combine/Publishers/Publishers.HandleEvents.swift +260 -0
- package/Sources/Combine/Publishers/Publishers.IgnoreOutput.swift +109 -0
- package/Sources/Combine/Publishers/Publishers.Last.swift +252 -0
- package/Sources/Combine/Publishers/Publishers.MakeConnectable.swift +82 -0
- package/Sources/Combine/Publishers/Publishers.Map.swift +351 -0
- package/Sources/Combine/Publishers/Publishers.MapError.swift +140 -0
- package/Sources/Combine/Publishers/Publishers.MeasureInterval.swift +187 -0
- package/Sources/Combine/Publishers/Publishers.Multicast.swift +284 -0
- package/Sources/Combine/Publishers/Publishers.Output.swift +241 -0
- package/Sources/Combine/Publishers/Publishers.PrefixUntilOutput.swift +197 -0
- package/Sources/Combine/Publishers/Publishers.PrefixWhile.swift +176 -0
- package/Sources/Combine/Publishers/Publishers.Print.swift +206 -0
- package/Sources/Combine/Publishers/Publishers.ReceiveOn.swift +227 -0
- package/Sources/Combine/Publishers/Publishers.Reduce.swift +204 -0
- package/Sources/Combine/Publishers/Publishers.RemoveDuplicates.swift +264 -0
- package/Sources/Combine/Publishers/Publishers.ReplaceEmpty.swift +201 -0
- package/Sources/Combine/Publishers/Publishers.ReplaceError.swift +211 -0
- package/Sources/Combine/Publishers/Publishers.Retry.swift +274 -0
- package/Sources/Combine/Publishers/Publishers.Scan.swift +331 -0
- package/Sources/Combine/Publishers/Publishers.Sequence.swift +437 -0
- package/Sources/Combine/Publishers/Publishers.SetFailureType.swift +120 -0
- package/Sources/Combine/Publishers/Publishers.Share.swift +104 -0
- package/Sources/Combine/Publishers/Publishers.SubscribeOn.swift +197 -0
- package/Sources/Combine/Publishers/Publishers.SwitchToLatest.swift +444 -0
- package/Sources/Combine/Publishers/Publishers.Throttle.swift +359 -0
- package/Sources/Combine/Publishers/Publishers.Timeout.swift +301 -0
- package/Sources/Combine/Publishers/Publishers.Zip.swift +720 -0
- package/Sources/Combine/Publishers/Publishers.swift +13 -0
- package/Sources/Combine/Publishers/Record.swift +237 -0
- package/Sources/Combine/Publishers/Result.Publisher.swift +337 -0
- package/Sources/Combine/Result.swift +46 -0
- package/Sources/Combine/Scheduler.swift +89 -0
- package/Sources/Combine/Schedulers.swift +211 -0
- package/Sources/Combine/Subject+Void.swift +17 -0
- package/Sources/Combine/Subscriber+Void.swift +20 -0
- package/Sources/Combine/Subscribers/Subscribers.Assign.swift +175 -0
- package/Sources/Combine/Subscribers/Subscribers.Completion.swift +90 -0
- package/Sources/Combine/Subscribers/Subscribers.Demand.swift +476 -0
- package/Sources/Combine/Subscribers/Subscribers.Sink.swift +206 -0
- package/Sources/Combine/Subscribers/Subscribers.swift +9 -0
- package/Sources/Combine/Subscription.swift +22 -0
- package/Sources/Combine/Subscriptions.swift +42 -0
- package/Sources/Combine/SwiftUIObservation.swift +10 -0
- package/Sources/Combine/_Introspection.swift +107 -0
- package/Sources/CommonCrypto/CommonCrypto.swift +80 -0
- package/Sources/Compression/Compression.swift +365 -0
- package/Sources/Compression/Deflate.swift +407 -0
- package/Sources/Compression/Zlib.swift +179 -0
- package/Sources/CoreFoundationTypes/CoreFoundationTypes.swift +101 -0
- package/Sources/CoreGraphics/CoreGraphics.swift +411 -0
- package/Sources/CoreGraphics/ProjectionTransforms.swift +28 -0
- package/Sources/CoreHaptics/CoreHaptics.swift +399 -0
- package/Sources/CoreImage/CIColor.swift +41 -0
- package/Sources/CoreImage/CIContext.swift +31 -0
- package/Sources/CoreImage/CIDetector.swift +57 -0
- package/Sources/CoreImage/CIFilter.swift +243 -0
- package/Sources/CoreImage/CIFilterBuiltins.swift +136 -0
- package/Sources/CoreImage/CIImage.swift +162 -0
- package/Sources/CoreImage/QRCode.swift +393 -0
- package/Sources/CoreLocation/Coordinate.swift +30 -0
- package/Sources/CoreLocation/Location.swift +65 -0
- package/Sources/CoreML/Evaluation.swift +414 -0
- package/Sources/CoreML/FeatureValue.swift +266 -0
- package/Sources/CoreML/Model.swift +269 -0
- package/Sources/CoreML/MultiArray.swift +92 -0
- package/Sources/CoreML/Specification.swift +233 -0
- package/Sources/CoreText/CoreText.swift +64 -0
- package/Sources/CoreTransferable/CoreTransferable.swift +606 -0
- package/Sources/CryptoKit/ChaChaPoly.swift +258 -0
- package/Sources/CryptoKit/CryptoKit.swift +375 -0
- package/Sources/CryptoKit/Curve25519.swift +317 -0
- package/Sources/CryptoKit/P256.swift +321 -0
- package/Sources/FoundationBridge/AppStorage.swift +165 -0
- package/Sources/FoundationBridge/AssetResources.swift +90 -0
- package/Sources/FoundationBridge/AsyncBytes.swift +128 -0
- package/Sources/FoundationBridge/AsyncImage.swift +116 -0
- package/Sources/FoundationBridge/AttributedStrings.swift +16 -0
- package/Sources/FoundationBridge/Bundle.swift +119 -0
- package/Sources/FoundationBridge/CombineExports.swift +8 -0
- package/Sources/FoundationBridge/CoreFoundation.swift +77 -0
- package/Sources/FoundationBridge/Dispatch.swift +458 -0
- package/Sources/FoundationBridge/EnvironmentFoundation.swift +41 -0
- package/Sources/FoundationBridge/FileImporter.swift +128 -0
- package/Sources/FoundationBridge/FileSystem.swift +68 -0
- package/Sources/FoundationBridge/FoundationBridge.swift +29 -0
- package/Sources/FoundationBridge/HostResolution.swift +31 -0
- package/Sources/FoundationBridge/ItemProvider.swift +655 -0
- package/Sources/FoundationBridge/KeyValueObserving.swift +138 -0
- package/Sources/FoundationBridge/Links.swift +127 -0
- package/Sources/FoundationBridge/ListFormatter.swift +32 -0
- package/Sources/FoundationBridge/Locale.swift +86 -0
- package/Sources/FoundationBridge/Localization.swift +149 -0
- package/Sources/FoundationBridge/Locks.swift +50 -0
- package/Sources/FoundationBridge/Markdown.swift +527 -0
- package/Sources/FoundationBridge/MeasurementFormat.swift +95 -0
- package/Sources/FoundationBridge/NotificationCenter.swift +154 -0
- package/Sources/FoundationBridge/OpenURLHandlers.swift +60 -0
- package/Sources/FoundationBridge/Operation.swift +195 -0
- package/Sources/FoundationBridge/ProcessInfo.swift +32 -0
- package/Sources/FoundationBridge/RelativeDateTimeFormatter.swift +136 -0
- package/Sources/FoundationBridge/SceneStorage.swift +78 -0
- package/Sources/FoundationBridge/SecurityExports.swift +8 -0
- package/Sources/FoundationBridge/Selector.swift +226 -0
- package/Sources/FoundationBridge/StringComparators.swift +17 -0
- package/Sources/FoundationBridge/Table.swift +211 -0
- package/Sources/FoundationBridge/TextAttributes.swift +42 -0
- package/Sources/FoundationBridge/Timer.swift +53 -0
- package/Sources/FoundationBridge/UITextChecker.swift +30 -0
- package/Sources/FoundationBridge/URLSession.swift +718 -0
- package/Sources/FoundationBridge/UserDefaults.swift +183 -0
- package/Sources/FoundationBridge/WebAuthRedirects.swift +227 -0
- package/Sources/FoundationBridge/WebSocket.swift +187 -0
- package/Sources/FoundationModels/FoundationModels.swift +1098 -0
- package/Sources/ImageIO/GIF.swift +72 -0
- package/Sources/ImageIO/ImageIO.swift +248 -0
- package/Sources/ImageIO/ImageTypes.swift +28 -0
- package/Sources/LinkPresentation/LinkPresentation.swift +249 -0
- package/Sources/LocalAuthentication/LAContext.swift +86 -0
- package/Sources/MapKit/Geometry.swift +223 -0
- package/Sources/MapKit/Map.swift +638 -0
- package/Sources/MapKit/MapView.swift +229 -0
- package/Sources/MobileCoreServices/MobileCoreServices.swift +28 -0
- package/Sources/NaturalLanguage/LanguageIdentifier.swift +317 -0
- package/Sources/NaturalLanguage/NaturalLanguage.swift +135 -0
- package/Sources/OSLog/OSLog.swift +6 -0
- package/Sources/Photos/Photos.swift +572 -0
- package/Sources/PhotosUI/PhotosPicker.swift +248 -0
- package/Sources/PhotosUI/PhotosPickerItem.swift +261 -0
- package/Sources/QuickLook/QuickLook.swift +168 -0
- package/Sources/SafariServices/SafariServices.swift +106 -0
- package/Sources/Security/Security.swift +332 -0
- package/Sources/StoreKit/AppStore.swift +207 -0
- package/Sources/StoreKit/Products.swift +280 -0
- package/Sources/StoreKit/RequestReview.swift +28 -0
- package/Sources/StoreKit/StoreKit1.swift +486 -0
- package/Sources/StoreKit/StoreViews.swift +428 -0
- package/Sources/StoreKit/Transactions.swift +197 -0
- package/Sources/SwiftData/Macros.swift +58 -0
- package/Sources/SwiftData/ModelActor.swift +38 -0
- package/Sources/SwiftData/ModelContainer.swift +129 -0
- package/Sources/SwiftData/ModelContext.swift +451 -0
- package/Sources/SwiftData/PersistentModel.swift +238 -0
- package/Sources/SwiftData/Properties.swift +261 -0
- package/Sources/SwiftData/Query.swift +256 -0
- package/Sources/SwiftData/Schema.swift +192 -0
- package/Sources/SwiftData/Store.swift +146 -0
- package/Sources/SwiftData/StringPredicates.swift +125 -0
- package/Sources/SwiftDataMacros/EntryMacro.swift +82 -0
- package/Sources/SwiftDataMacros/GenerableMacro.swift +183 -0
- package/Sources/SwiftDataMacros/ModelActorMacro.swift +46 -0
- package/Sources/SwiftDataMacros/ModelMacro.swift +260 -0
- package/Sources/SwiftDataMacros/Plugin.swift +18 -0
- package/Sources/SwiftDataMacros/PredicateMacro.swift +1244 -0
- package/Sources/SwiftUI/API/Accessibility.swift +181 -0
- package/Sources/SwiftUI/API/AccessibilityExtras.swift +33 -0
- package/Sources/SwiftUI/API/AccessibilityFocus.swift +63 -0
- package/Sources/SwiftUI/API/Alert.swift +221 -0
- package/Sources/SwiftUI/API/AlignmentGuides.swift +65 -0
- package/Sources/SwiftUI/API/Animation.swift +285 -0
- package/Sources/SwiftUI/API/App.swift +87 -0
- package/Sources/SwiftUI/API/BindingCollections.swift +35 -0
- package/Sources/SwiftUI/API/BindingForEach.swift +27 -0
- package/Sources/SwiftUI/API/Bitmaps.swift +254 -0
- package/Sources/SwiftUI/API/ButtonStyles.swift +96 -0
- package/Sources/SwiftUI/API/Canvas.swift +337 -0
- package/Sources/SwiftUI/API/Color.swift +237 -0
- package/Sources/SwiftUI/API/ColorEffects.swift +52 -0
- package/Sources/SwiftUI/API/ColorPickerAndLabeledContent.swift +138 -0
- package/Sources/SwiftUI/API/ColorSpaces.swift +161 -0
- package/Sources/SwiftUI/API/Commands.swift +106 -0
- package/Sources/SwiftUI/API/ContainerBackground.swift +28 -0
- package/Sources/SwiftUI/API/ContentShape.swift +33 -0
- package/Sources/SwiftUI/API/ContentSizeCategory.swift +35 -0
- package/Sources/SwiftUI/API/ContentUnavailable.swift +101 -0
- package/Sources/SwiftUI/API/Controls.swift +300 -0
- package/Sources/SwiftUI/API/CustomLayout.swift +442 -0
- package/Sources/SwiftUI/API/CustomToolbarContent.swift +46 -0
- package/Sources/SwiftUI/API/Decorations.swift +92 -0
- package/Sources/SwiftUI/API/EditMode.swift +212 -0
- package/Sources/SwiftUI/API/Effects.swift +388 -0
- package/Sources/SwiftUI/API/Entry.swift +8 -0
- package/Sources/SwiftUI/API/Environment.swift +439 -0
- package/Sources/SwiftUI/API/EnvironmentSendable.swift +6 -0
- package/Sources/SwiftUI/API/Focus.swift +137 -0
- package/Sources/SwiftUI/API/Font.swift +131 -0
- package/Sources/SwiftUI/API/Gauge.swift +290 -0
- package/Sources/SwiftUI/API/Geometry.swift +89 -0
- package/Sources/SwiftUI/API/GeometryEffects.swift +232 -0
- package/Sources/SwiftUI/API/GeometryReader.swift +135 -0
- package/Sources/SwiftUI/API/GestureState.swift +65 -0
- package/Sources/SwiftUI/API/Gestures.swift +342 -0
- package/Sources/SwiftUI/API/Glass.swift +127 -0
- package/Sources/SwiftUI/API/Grid.swift +188 -0
- package/Sources/SwiftUI/API/GroupBoxAndControlGroup.swift +130 -0
- package/Sources/SwiftUI/API/KeyPress.swift +54 -0
- package/Sources/SwiftUI/API/LabelStyle.swift +124 -0
- package/Sources/SwiftUI/API/Layout.swift +220 -0
- package/Sources/SwiftUI/API/LazyStacks.swift +49 -0
- package/Sources/SwiftUI/API/LegacyAlert.swift +97 -0
- package/Sources/SwiftUI/API/Lists.swift +331 -0
- package/Sources/SwiftUI/API/Menu.swift +58 -0
- package/Sources/SwiftUI/API/Modifiers.swift +313 -0
- package/Sources/SwiftUI/API/MoreModifiers.swift +100 -0
- package/Sources/SwiftUI/API/Namespace.swift +44 -0
- package/Sources/SwiftUI/API/Navigation.swift +386 -0
- package/Sources/SwiftUI/API/NavigationDestinationBindings.swift +55 -0
- package/Sources/SwiftUI/API/ObservableObject.swift +293 -0
- package/Sources/SwiftUI/API/OnChange.swift +48 -0
- package/Sources/SwiftUI/API/Path.swift +543 -0
- package/Sources/SwiftUI/API/Phase8Controls.swift +411 -0
- package/Sources/SwiftUI/API/PhaseAnimator.swift +130 -0
- package/Sources/SwiftUI/API/Picker.swift +185 -0
- package/Sources/SwiftUI/API/PointerAndKeyboard.swift +77 -0
- package/Sources/SwiftUI/API/Popover.swift +41 -0
- package/Sources/SwiftUI/API/Preferences.swift +262 -0
- package/Sources/SwiftUI/API/Presentation.swift +122 -0
- package/Sources/SwiftUI/API/PresentationExtras.swift +60 -0
- package/Sources/SwiftUI/API/Primitives.swift +517 -0
- package/Sources/SwiftUI/API/Publishers.swift +107 -0
- package/Sources/SwiftUI/API/Redaction.swift +75 -0
- package/Sources/SwiftUI/API/RowActions.swift +84 -0
- package/Sources/SwiftUI/API/Scenes.swift +131 -0
- package/Sources/SwiftUI/API/ScrollModifiers.swift +132 -0
- package/Sources/SwiftUI/API/ScrollTargets.swift +104 -0
- package/Sources/SwiftUI/API/ScrollViewReader.swift +144 -0
- package/Sources/SwiftUI/API/SectionSupplements.swift +96 -0
- package/Sources/SwiftUI/API/Shape.swift +214 -0
- package/Sources/SwiftUI/API/ShapeStyle.swift +409 -0
- package/Sources/SwiftUI/API/ShapeTrim.swift +78 -0
- package/Sources/SwiftUI/API/Sharing.swift +193 -0
- package/Sources/SwiftUI/API/StackLayouts.swift +199 -0
- package/Sources/SwiftUI/API/State.swift +144 -0
- package/Sources/SwiftUI/API/StatusGaps.swift +121 -0
- package/Sources/SwiftUI/API/StrokeStyle.swift +30 -0
- package/Sources/SwiftUI/API/SymbolEffects.swift +203 -0
- package/Sources/SwiftUI/API/TabContent.swift +841 -0
- package/Sources/SwiftUI/API/Table.swift +382 -0
- package/Sources/SwiftUI/API/Tabs.swift +263 -0
- package/Sources/SwiftUI/API/Tasks.swift +35 -0
- package/Sources/SwiftUI/API/Text.swift +386 -0
- package/Sources/SwiftUI/API/TextDates.swift +61 -0
- package/Sources/SwiftUI/API/TextDecorations.swift +52 -0
- package/Sources/SwiftUI/API/TextFieldAxis.swift +103 -0
- package/Sources/SwiftUI/API/TextFieldCommit.swift +52 -0
- package/Sources/SwiftUI/API/Timeline.swift +212 -0
- package/Sources/SwiftUI/API/Toolbar.swift +251 -0
- package/Sources/SwiftUI/API/Transfer.swift +145 -0
- package/Sources/SwiftUI/API/UnevenRoundedRectangle.swift +66 -0
- package/Sources/SwiftUI/API/Video.swift +64 -0
- package/Sources/SwiftUI/API/View.swift +215 -0
- package/Sources/SwiftUI/API/ViewModifier.swift +43 -0
- package/Sources/SwiftUI/API/VisualEffect.swift +155 -0
- package/Sources/SwiftUI/API/Windows.swift +25 -0
- package/Sources/SwiftUI/Charts/Axis.swift +325 -0
- package/Sources/SwiftUI/Charts/AxisFormatsAndRanges.swift +68 -0
- package/Sources/SwiftUI/Charts/Chart.swift +660 -0
- package/Sources/SwiftUI/Charts/ChartContent.swift +376 -0
- package/Sources/SwiftUI/Charts/ChartProxy.swift +57 -0
- package/Sources/SwiftUI/Charts/Marks.swift +204 -0
- package/Sources/SwiftUI/Charts/Plottable.swift +99 -0
- package/Sources/SwiftUI/Charts/Scales.swift +326 -0
- package/Sources/SwiftUI/Localization/Localization.swift +498 -0
- package/Sources/SwiftUI/Localization/PluralRules.swift +127 -0
- package/Sources/SwiftUI/Runtime/Executor.swift +85 -0
- package/Sources/SwiftUI/Runtime/Exports.swift +101 -0
- package/Sources/SwiftUI/Runtime/ImageSource.swift +310 -0
- package/Sources/SwiftUI/Runtime/JSON.swift +143 -0
- package/Sources/SwiftUI/Runtime/JSONParser.swift +443 -0
- package/Sources/SwiftUI/Runtime/LazyRows.swift +99 -0
- package/Sources/SwiftUI/Runtime/Measurements.swift +140 -0
- package/Sources/SwiftUI/Runtime/Ops.swift +152 -0
- package/Sources/SwiftUI/Runtime/Reconciler.swift +219 -0
- package/Sources/SwiftUI/Runtime/Replay.swift +382 -0
- package/Sources/SwiftUI/Runtime/Runtime.swift +2146 -0
- package/Sources/SwiftUI/Runtime/Sameness.swift +152 -0
- package/Sources/SwiftUI/Runtime/ViewPath.swift +89 -0
- package/Sources/SwiftUI/Runtime/ViewTraits.swift +175 -0
- package/Sources/SwiftUI/Runtime/WebAuthHeadless.swift +49 -0
- package/Sources/Symbols/Symbols.swift +25 -0
- package/Sources/Translation/Translation.swift +423 -0
- package/Sources/UIKit/Activity.swift +213 -0
- package/Sources/UIKit/Alerts.swift +69 -0
- package/Sources/UIKit/AppDelegate.swift +222 -0
- package/Sources/UIKit/Appearance.swift +84 -0
- package/Sources/UIKit/ColorConversions.swift +70 -0
- package/Sources/UIKit/Controls.swift +225 -0
- package/Sources/UIKit/Device.swift +200 -0
- package/Sources/UIKit/Feedback.swift +65 -0
- package/Sources/UIKit/Font.swift +307 -0
- package/Sources/UIKit/Graphics.swift +204 -0
- package/Sources/UIKit/HostingController.swift +185 -0
- package/Sources/UIKit/Identity.swift +24 -0
- package/Sources/UIKit/Introspectable.swift +510 -0
- package/Sources/UIKit/Pasteboard.swift +363 -0
- package/Sources/UIKit/PhotoAlbum.swift +81 -0
- package/Sources/UIKit/RemoteNotifications.swift +15 -0
- package/Sources/UIKit/Representable.swift +288 -0
- package/Sources/UIKit/SafeArea.swift +12 -0
- package/Sources/UIKit/SceneDelegates.swift +132 -0
- package/Sources/UIKit/Scenes.swift +40 -0
- package/Sources/UIKit/ScrollView.swift +157 -0
- package/Sources/UIKit/ShortcutItems.swift +67 -0
- package/Sources/UIKit/SymbolConfiguration.swift +124 -0
- package/Sources/UIKit/TargetAction.swift +123 -0
- package/Sources/UIKit/TextPaste.swift +161 -0
- package/Sources/UIKit/TextView.swift +538 -0
- package/Sources/UIKit/UIKit.swift +292 -0
- package/Sources/UIKit/UIView.swift +855 -0
- package/Sources/UIKit/ViewTranslation.swift +311 -0
- package/Sources/UniformTypeIdentifiers/UTType.swift +196 -0
- package/Sources/UserNotifications/Content.swift +370 -0
- package/Sources/UserNotifications/NotificationCenter.swift +309 -0
- package/Sources/WeatherKit/WeatherKit.swift +228 -0
- package/Sources/WebKit/WebKit.swift +245 -0
- package/Sources/os/os.swift +376 -0
- package/Sources/zlib/zlib.swift +6 -0
- package/index.d.ts +2 -0
- package/index.mjs +16 -0
- package/manifest.d.mts +2 -0
- package/manifest.mjs +39 -0
- package/package.json +30 -4
- package/sync-sources.mjs +33 -0
|
@@ -0,0 +1,606 @@
|
|
|
1
|
+
// `import CoreTransferable` for the browser: `Transferable`, the protocol a
|
|
2
|
+
// type adopts to say how it turns into bytes or a file of some content type
|
|
3
|
+
// and back, and the representations it says it with (`DataRepresentation`,
|
|
4
|
+
// `FileRepresentation`, `ProxyRepresentation`, `CodableRepresentation`).
|
|
5
|
+
// On iOS SwiftUI re-exports this module, and so does the shim's SwiftUI
|
|
6
|
+
// (this module sits under it), so `struct Photo: Transferable` compiles with
|
|
7
|
+
// `import SwiftUI` alone.
|
|
8
|
+
//
|
|
9
|
+
// The representations are real: they run. A value exports through the first
|
|
10
|
+
// representation that can (`ShareLink` sends the bytes or the file to the
|
|
11
|
+
// page, which shares them with the Web Share API or downloads them), and a
|
|
12
|
+
// type imports through the first one that accepts the content type offered
|
|
13
|
+
// (`PhotosPickerItem.loadTransferable`, `NSItemProvider.loadTransferable`).
|
|
14
|
+
// A received file is a copy in the temporary directory that is removed once
|
|
15
|
+
// the importing closure returns, as on iOS. What the browser has no use for
|
|
16
|
+
// is kept and ignored: visibility (there is no other app or process to hide
|
|
17
|
+
// from) and `shouldAttemptToOpenInPlace` beyond reporting `isOriginalFile`.
|
|
18
|
+
// docs/ops-protocol.md, "Sharing and media".
|
|
19
|
+
|
|
20
|
+
@_exported import UniformTypeIdentifiers
|
|
21
|
+
import Foundation
|
|
22
|
+
|
|
23
|
+
// MARK: - Transferable
|
|
24
|
+
|
|
25
|
+
/// A type that can be shared, dragged, pasted or picked: it lists the
|
|
26
|
+
/// representations it exports and imports, in order of preference.
|
|
27
|
+
public protocol Transferable {
|
|
28
|
+
associatedtype Representation: TransferRepresentation
|
|
29
|
+
@TransferRepresentationBuilder<Self> static var transferRepresentation: Representation { get }
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/// One way of turning an `Item` into content of some type, or back.
|
|
33
|
+
/// Compose them with the builder; your own representation is a `body` of others.
|
|
34
|
+
public protocol TransferRepresentation<Item> {
|
|
35
|
+
associatedtype Item: Transferable
|
|
36
|
+
associatedtype Body: TransferRepresentation
|
|
37
|
+
@TransferRepresentationBuilder<Item> var body: Body { get }
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
extension Never: Transferable {
|
|
41
|
+
public static var transferRepresentation: Never { return fatalError("Never has no representation") }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
extension Never: TransferRepresentation {
|
|
45
|
+
public typealias Item = Never
|
|
46
|
+
public var body: Never { return fatalError("Never has no representation") }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/// Who may see a representation. Kept: in the browser the app is alone, so
|
|
50
|
+
/// every representation is visible to it.
|
|
51
|
+
public struct TransferRepresentationVisibility: Hashable, Sendable {
|
|
52
|
+
let name: String
|
|
53
|
+
public static let all = TransferRepresentationVisibility(name: "all")
|
|
54
|
+
public static let team = TransferRepresentationVisibility(name: "team")
|
|
55
|
+
public static let group = TransferRepresentationVisibility(name: "group")
|
|
56
|
+
public static let ownProcess = TransferRepresentationVisibility(name: "ownProcess")
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// MARK: - Files
|
|
60
|
+
|
|
61
|
+
/// A file a value exports (`FileRepresentation`'s exporting closure returns one).
|
|
62
|
+
public struct SentTransferredFile: Sendable {
|
|
63
|
+
public let file: URL
|
|
64
|
+
public let allowAccessingOriginalFile: Bool
|
|
65
|
+
|
|
66
|
+
public init(_ file: URL, allowAccessingOriginalFile: Bool = false) {
|
|
67
|
+
self.file = file
|
|
68
|
+
self.allowAccessingOriginalFile = allowAccessingOriginalFile
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/// A file handed to `FileRepresentation`'s importing closure: a copy in the
|
|
73
|
+
/// temporary directory (removed once the closure returns; copy it to keep
|
|
74
|
+
/// it), or the original when the representation asked to open in place and
|
|
75
|
+
/// the content was a file.
|
|
76
|
+
public struct ReceivedTransferredFile: Sendable {
|
|
77
|
+
public let file: URL
|
|
78
|
+
public let isOriginalFile: Bool
|
|
79
|
+
|
|
80
|
+
public init(_file file: URL, isOriginalFile: Bool) {
|
|
81
|
+
self.file = file
|
|
82
|
+
self.isOriginalFile = isOriginalFile
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// MARK: - The representations
|
|
87
|
+
|
|
88
|
+
/// The value as bytes of one content type.
|
|
89
|
+
public struct DataRepresentation<Item: Transferable>: TransferRepresentation, _TransferPrimitive {
|
|
90
|
+
public typealias Body = Never
|
|
91
|
+
public var body: Never { return fatalError("a primitive representation has no body") }
|
|
92
|
+
let node: _TransferNode
|
|
93
|
+
|
|
94
|
+
public init(contentType: UTType,
|
|
95
|
+
exporting: @escaping (Item) async throws -> Data,
|
|
96
|
+
importing: @escaping (Data) async throws -> Item) {
|
|
97
|
+
node = _TransferNode(exportType: contentType, importType: contentType,
|
|
98
|
+
exporter: Self.exporter(contentType, exporting), importer: Self.importer(importing))
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
public init(exportedContentType: UTType, exporting: @escaping (Item) async throws -> Data) {
|
|
102
|
+
node = _TransferNode(exportType: exportedContentType, importType: nil,
|
|
103
|
+
exporter: Self.exporter(exportedContentType, exporting), importer: nil)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
public init(importedContentType: UTType, importing: @escaping (Data) async throws -> Item) {
|
|
107
|
+
node = _TransferNode(exportType: nil, importType: importedContentType, exporter: nil, importer: Self.importer(importing))
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
private static func exporter(_ type: UTType, _ exporting: @escaping (Item) async throws -> Data) -> _TransferNode.Exporter {
|
|
111
|
+
{ item, _ in
|
|
112
|
+
nonisolated(unsafe) let value = item as! Item
|
|
113
|
+
return _TransferContent(contentType: type, data: try await exporting(value))
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
private static func importer(_ importing: @escaping (Data) async throws -> Item) -> _TransferNode.Importer {
|
|
118
|
+
{ content in try await importing(try content.loadData()) }
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
public var _transferNodes: [_TransferNode] { [node] }
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/// The value as a file of one content type.
|
|
125
|
+
public struct FileRepresentation<Item: Transferable>: TransferRepresentation, _TransferPrimitive {
|
|
126
|
+
public typealias Body = Never
|
|
127
|
+
public var body: Never { return fatalError("a primitive representation has no body") }
|
|
128
|
+
let node: _TransferNode
|
|
129
|
+
|
|
130
|
+
public init(contentType: UTType, shouldAttemptToOpenInPlace: Bool = false,
|
|
131
|
+
exporting: @escaping (Item) async throws -> SentTransferredFile,
|
|
132
|
+
importing: @escaping (ReceivedTransferredFile) async throws -> Item) {
|
|
133
|
+
node = _TransferNode(exportType: contentType, importType: contentType,
|
|
134
|
+
exporter: Self.exporter(contentType, exporting),
|
|
135
|
+
importer: Self.importer(inPlace: shouldAttemptToOpenInPlace, importing))
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
public init(exportedContentType: UTType, shouldAllowToOpenInPlace: Bool = false,
|
|
139
|
+
exporting: @escaping (Item) async throws -> SentTransferredFile) {
|
|
140
|
+
node = _TransferNode(exportType: exportedContentType, importType: nil,
|
|
141
|
+
exporter: Self.exporter(exportedContentType, exporting), importer: nil)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
public init(importedContentType: UTType, shouldAttemptToOpenInPlace: Bool = false,
|
|
145
|
+
importing: @escaping (ReceivedTransferredFile) async throws -> Item) {
|
|
146
|
+
node = _TransferNode(exportType: nil, importType: importedContentType, exporter: nil,
|
|
147
|
+
importer: Self.importer(inPlace: shouldAttemptToOpenInPlace, importing))
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
private static func exporter(_ type: UTType, _ exporting: @escaping (Item) async throws -> SentTransferredFile) -> _TransferNode.Exporter {
|
|
151
|
+
{ item, _ in
|
|
152
|
+
nonisolated(unsafe) let value = item as! Item
|
|
153
|
+
let sent = try await exporting(value)
|
|
154
|
+
return _TransferContent(contentType: type, file: sent.file, isOriginalFile: sent.allowAccessingOriginalFile,
|
|
155
|
+
suggestedName: sent.file.deletingPathExtension().lastPathComponent)
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
private static func importer(inPlace: Bool, _ importing: @escaping (ReceivedTransferredFile) async throws -> Item) -> _TransferNode.Importer {
|
|
160
|
+
{ content in
|
|
161
|
+
let received = try content.receivedFile(inPlace: inPlace)
|
|
162
|
+
defer { if !received.isOriginalFile { try? FileManager.default.removeItem(at: received.file) } }
|
|
163
|
+
return try await importing(received)
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
public var _transferNodes: [_TransferNode] { [node] }
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/// The value as another `Transferable` value (a `URL`, a `String`…), which
|
|
171
|
+
/// carries the content types.
|
|
172
|
+
public struct ProxyRepresentation<Item: Transferable, ProxyRepresentation: Transferable>: TransferRepresentation, _TransferPrimitive {
|
|
173
|
+
public typealias Body = Never
|
|
174
|
+
public var body: Never { return fatalError("a primitive representation has no body") }
|
|
175
|
+
let node: _TransferNode
|
|
176
|
+
|
|
177
|
+
public init(exporting: @escaping (Item) async throws -> ProxyRepresentation,
|
|
178
|
+
importing: @escaping (ProxyRepresentation) async throws -> Item) {
|
|
179
|
+
node = Self.node(exporting: exporting, importing: importing)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
public init(exporting: @escaping (Item) async throws -> ProxyRepresentation) {
|
|
183
|
+
node = Self.node(exporting: exporting, importing: nil)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
public init(importing: @escaping (ProxyRepresentation) async throws -> Item) {
|
|
187
|
+
node = Self.node(exporting: nil, importing: importing)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
private static func node(exporting: ((Item) async throws -> ProxyRepresentation)?,
|
|
191
|
+
importing: ((ProxyRepresentation) async throws -> Item)?) -> _TransferNode {
|
|
192
|
+
var exporter: _TransferNode.Exporter?
|
|
193
|
+
if let exporting {
|
|
194
|
+
exporter = { item, wanted in
|
|
195
|
+
nonisolated(unsafe) let value = item as! Item
|
|
196
|
+
return try await _Transfer.export(try await exporting(value), as: wanted)
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
var importer: _TransferNode.Importer?
|
|
200
|
+
if let importing {
|
|
201
|
+
importer = { content in
|
|
202
|
+
guard let proxy = try await _Transfer.import(ProxyRepresentation.self, from: content) else { return nil }
|
|
203
|
+
nonisolated(unsafe) let value = proxy
|
|
204
|
+
return try await importing(value)
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
var node = _TransferNode(exportType: nil, importType: nil, exporter: exporter, importer: importer)
|
|
208
|
+
node.proxyExportTypes = exporting == nil ? nil : { _Transfer.exportedContentTypes(ProxyRepresentation.self) }
|
|
209
|
+
node.proxyImportTypes = importing == nil ? nil : { _Transfer.importedContentTypes(ProxyRepresentation.self) }
|
|
210
|
+
return node
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
public var _transferNodes: [_TransferNode] { [node] }
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/// What `CodableRepresentation` encodes with: `JSONEncoder` and
|
|
217
|
+
/// `PropertyListEncoder` (Combine's `TopLevelEncoder`, which the browser's
|
|
218
|
+
/// Foundation does not have, for this purpose).
|
|
219
|
+
public protocol _TransferTopLevelEncoder {
|
|
220
|
+
func encode<T: Encodable>(_ value: T) throws -> Data
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/// What `CodableRepresentation` decodes with.
|
|
224
|
+
public protocol _TransferTopLevelDecoder {
|
|
225
|
+
func decode<T: Decodable>(_ type: T.Type, from data: Data) throws -> T
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
extension JSONEncoder: _TransferTopLevelEncoder {}
|
|
229
|
+
extension JSONDecoder: _TransferTopLevelDecoder {}
|
|
230
|
+
extension PropertyListEncoder: _TransferTopLevelEncoder {}
|
|
231
|
+
extension PropertyListDecoder: _TransferTopLevelDecoder {}
|
|
232
|
+
|
|
233
|
+
/// The value encoded with `Codable`, as JSON unless you pass a coder.
|
|
234
|
+
public struct CodableRepresentation<Item: Transferable & Codable, Encoder: _TransferTopLevelEncoder, Decoder: _TransferTopLevelDecoder>:
|
|
235
|
+
TransferRepresentation, _TransferPrimitive {
|
|
236
|
+
public typealias Body = Never
|
|
237
|
+
public var body: Never { return fatalError("a primitive representation has no body") }
|
|
238
|
+
let node: _TransferNode
|
|
239
|
+
|
|
240
|
+
public init(for itemType: Item.Type = Item.self, contentType: UTType, encoder: Encoder, decoder: Decoder) {
|
|
241
|
+
let encode = Self.encoding(encoder)
|
|
242
|
+
let decode = Self.decoding(decoder)
|
|
243
|
+
node = _TransferNode(
|
|
244
|
+
exportType: contentType, importType: contentType,
|
|
245
|
+
exporter: { item, _ in _TransferContent(contentType: contentType, data: try encode(item as! Item)) },
|
|
246
|
+
importer: { content in try decode(try content.loadData()) })
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
private static func encoding(_ encoder: Encoder) -> (Item) throws -> Data {
|
|
250
|
+
let box = _UncheckedBox(encoder)
|
|
251
|
+
return { item in try box.value.encode(item) }
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
private static func decoding(_ decoder: Decoder) -> (Data) throws -> Item {
|
|
255
|
+
let box = _UncheckedBox(decoder)
|
|
256
|
+
return { data in try box.value.decode(Item.self, from: data) }
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
public var _transferNodes: [_TransferNode] { [node] }
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
extension CodableRepresentation where Encoder == JSONEncoder, Decoder == JSONDecoder {
|
|
263
|
+
public init(for itemType: Item.Type = Item.self, contentType: UTType) {
|
|
264
|
+
self.init(for: itemType, contentType: contentType, encoder: JSONEncoder(), decoder: JSONDecoder())
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// MARK: - Modifiers
|
|
269
|
+
|
|
270
|
+
extension TransferRepresentation {
|
|
271
|
+
/// The file name the exported content is offered under (the page uses
|
|
272
|
+
/// it for the shared or downloaded file).
|
|
273
|
+
public func suggestedFileName(_ fileName: String) -> _TransferRepresentationList<Item> {
|
|
274
|
+
modified { $0.suggestedFileName = { _ in fileName } }
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
public func suggestedFileName(_ fileName: @escaping (Item) -> String?) -> _TransferRepresentationList<Item> {
|
|
278
|
+
modified { $0.suggestedFileName = { fileName($0 as! Item) } }
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/// Exports only the values for which `condition` holds.
|
|
282
|
+
public func exportingCondition(_ condition: @escaping (Item) -> Bool) -> _TransferRepresentationList<Item> {
|
|
283
|
+
modified { $0.exportingCondition = { condition($0 as! Item) } }
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/// Kept, with nothing to apply it to: the app is alone in the browser.
|
|
287
|
+
public func visibility(_ visibility: TransferRepresentationVisibility) -> _TransferRepresentationList<Item> {
|
|
288
|
+
modified { $0.visibility = visibility }
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
private func modified(_ change: (inout _TransferNode) -> Void) -> _TransferRepresentationList<Item> {
|
|
292
|
+
var nodes = _Transfer.nodes(of: self)
|
|
293
|
+
for index in nodes.indices { change(&nodes[index]) }
|
|
294
|
+
return _TransferRepresentationList(nodes: nodes)
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// MARK: - Builder
|
|
299
|
+
|
|
300
|
+
/// Several representations, in order of preference: what the builder makes.
|
|
301
|
+
public struct _TransferRepresentationList<Item: Transferable>: TransferRepresentation, _TransferPrimitive {
|
|
302
|
+
public typealias Body = Never
|
|
303
|
+
public var body: Never { return fatalError("a primitive representation has no body") }
|
|
304
|
+
public let _transferNodes: [_TransferNode]
|
|
305
|
+
|
|
306
|
+
public init(nodes: [_TransferNode]) { _transferNodes = nodes }
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
@resultBuilder
|
|
310
|
+
public enum TransferRepresentationBuilder<Item: Transferable> {
|
|
311
|
+
public static func buildExpression<R: TransferRepresentation>(_ representation: R) -> _TransferRepresentationList<Item> where R.Item == Item {
|
|
312
|
+
_TransferRepresentationList(nodes: _Transfer.nodes(of: representation))
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
public static func buildBlock() -> _TransferRepresentationList<Item> {
|
|
316
|
+
_TransferRepresentationList(nodes: [])
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
public static func buildBlock(_ components: _TransferRepresentationList<Item>...) -> _TransferRepresentationList<Item> {
|
|
320
|
+
_TransferRepresentationList(nodes: components.flatMap(\._transferNodes))
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
public static func buildOptional(_ component: _TransferRepresentationList<Item>?) -> _TransferRepresentationList<Item> {
|
|
324
|
+
component ?? _TransferRepresentationList(nodes: [])
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
public static func buildEither(first component: _TransferRepresentationList<Item>) -> _TransferRepresentationList<Item> { component }
|
|
328
|
+
public static func buildEither(second component: _TransferRepresentationList<Item>) -> _TransferRepresentationList<Item> { component }
|
|
329
|
+
public static func buildLimitedAvailability(_ component: _TransferRepresentationList<Item>) -> _TransferRepresentationList<Item> { component }
|
|
330
|
+
public static func buildArray(_ components: [_TransferRepresentationList<Item>]) -> _TransferRepresentationList<Item> {
|
|
331
|
+
_TransferRepresentationList(nodes: components.flatMap(\._transferNodes))
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// MARK: - Exporting and importing
|
|
336
|
+
|
|
337
|
+
extension Transferable {
|
|
338
|
+
/// The content types the type exports, in order of preference.
|
|
339
|
+
public static func exportedContentTypes(_ visibility: TransferRepresentationVisibility = .all) -> [UTType] {
|
|
340
|
+
_Transfer.exportedContentTypes(Self.self)
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/// The content types the type imports, in order of preference.
|
|
344
|
+
public static func importedContentTypes(_ visibility: TransferRepresentationVisibility = .all) -> [UTType] {
|
|
345
|
+
_Transfer.importedContentTypes(Self.self)
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/// The value's bytes as `contentType` (or a type conforming to it), from
|
|
349
|
+
/// the first representation that exports it.
|
|
350
|
+
nonisolated(nonsending) public func exported(as contentType: UTType) async throws -> Data {
|
|
351
|
+
guard let content = try await _Transfer.export(self, as: contentType) else {
|
|
352
|
+
throw _TransferError.noRepresentation(contentType)
|
|
353
|
+
}
|
|
354
|
+
return try content.loadData()
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/// A value made from `data` by the first representation that imports
|
|
358
|
+
/// `contentType` (with no type: the first that imports anything).
|
|
359
|
+
nonisolated(nonsending) public init(importing data: Data, contentType: UTType?) async throws {
|
|
360
|
+
let types = contentType.map { [$0] } ?? Self.importedContentTypes()
|
|
361
|
+
for type in types {
|
|
362
|
+
if let value = try await _Transfer.import(Self.self, from: _TransferContent(contentType: type, data: data)) {
|
|
363
|
+
self = value
|
|
364
|
+
return
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
throw _TransferError.noRepresentation(contentType ?? .data)
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/// Why a transfer failed.
|
|
372
|
+
public enum _TransferError: Error, CustomStringConvertible {
|
|
373
|
+
case noRepresentation(UTType)
|
|
374
|
+
case noContent
|
|
375
|
+
|
|
376
|
+
public var description: String {
|
|
377
|
+
switch self {
|
|
378
|
+
case .noRepresentation(let type): "no representation for \(type.identifier)"
|
|
379
|
+
case .noContent: "the content has no data"
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/// Content on its way out of a value or into one: bytes or a file, of a type.
|
|
385
|
+
public struct _TransferContent: @unchecked Sendable {
|
|
386
|
+
public var contentType: UTType
|
|
387
|
+
public var data: Data?
|
|
388
|
+
public var file: URL?
|
|
389
|
+
/// Whether `file` is the exporter's own (not a copy made for the transfer).
|
|
390
|
+
public var isOriginalFile: Bool
|
|
391
|
+
/// The file name (without extension) to offer the content under.
|
|
392
|
+
public var suggestedName: String?
|
|
393
|
+
/// A `Transferable` value exported through a `ProxyRepresentation` to a
|
|
394
|
+
/// `String` or `URL` (the page shares those as text and links).
|
|
395
|
+
public var value: Any?
|
|
396
|
+
|
|
397
|
+
public init(contentType: UTType, data: Data? = nil, file: URL? = nil, isOriginalFile: Bool = false,
|
|
398
|
+
suggestedName: String? = nil, value: Any? = nil) {
|
|
399
|
+
self.contentType = contentType
|
|
400
|
+
self.data = data
|
|
401
|
+
self.file = file
|
|
402
|
+
self.isOriginalFile = isOriginalFile
|
|
403
|
+
self.suggestedName = suggestedName
|
|
404
|
+
self.value = value
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/// The bytes: `data`, or the file's contents.
|
|
408
|
+
public func loadData() throws -> Data {
|
|
409
|
+
if let data { return data }
|
|
410
|
+
if let file { return try Data(contentsOf: file) }
|
|
411
|
+
throw _TransferError.noContent
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/// A file name with the content type's extension.
|
|
415
|
+
public var fileName: String {
|
|
416
|
+
let base = suggestedName.flatMap { $0.isEmpty ? nil : $0 } ?? file?.deletingPathExtension().lastPathComponent ?? "Shared"
|
|
417
|
+
if let file, !file.pathExtension.isEmpty { return "\(base).\(file.pathExtension)" }
|
|
418
|
+
guard let ext = contentType.preferredFilenameExtension else { return base }
|
|
419
|
+
return "\(base).\(ext)"
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/// The file an importing `FileRepresentation` receives: the original in
|
|
423
|
+
/// place when asked for and there is one, else a copy (or the bytes
|
|
424
|
+
/// written) in the temporary directory.
|
|
425
|
+
func receivedFile(inPlace: Bool) throws -> ReceivedTransferredFile {
|
|
426
|
+
if let file, inPlace { return ReceivedTransferredFile(_file: file, isOriginalFile: true) }
|
|
427
|
+
let folder = FileManager.default.temporaryDirectory.appendingPathComponent("Transfers-\(UUID().uuidString)", isDirectory: true)
|
|
428
|
+
try FileManager.default.createDirectory(at: folder, withIntermediateDirectories: true)
|
|
429
|
+
let copy = folder.appendingPathComponent(fileName)
|
|
430
|
+
if let file { try FileManager.default.copyItem(at: file, to: copy) } else { try loadData().write(to: copy) }
|
|
431
|
+
return ReceivedTransferredFile(_file: copy, isOriginalFile: false)
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/// One representation, with the item type erased: what the shim's
|
|
436
|
+
/// `ShareLink`, `NSItemProvider` and `PhotosPickerItem` walk.
|
|
437
|
+
public struct _TransferNode: @unchecked Sendable {
|
|
438
|
+
// Not `@Sendable`: the browser runs one thread, and the nodes are
|
|
439
|
+
// `@unchecked Sendable`. The app's closures are not `@Sendable` either,
|
|
440
|
+
// so a closure written in a main-actor type (a package with main-actor
|
|
441
|
+
// default isolation, as Ice Cubes' are) stays on the main actor and may
|
|
442
|
+
// call that type's initializers; being async, it hops there when called.
|
|
443
|
+
public typealias Exporter = nonisolated(nonsending) (Any, UTType?) async throws -> _TransferContent?
|
|
444
|
+
public typealias Importer = nonisolated(nonsending) (_TransferContent) async throws -> Any?
|
|
445
|
+
|
|
446
|
+
let exportType: UTType?
|
|
447
|
+
let importType: UTType?
|
|
448
|
+
let exporter: Exporter?
|
|
449
|
+
let importer: Importer?
|
|
450
|
+
var proxyExportTypes: (() -> [UTType])?
|
|
451
|
+
var proxyImportTypes: (() -> [UTType])?
|
|
452
|
+
var suggestedFileName: ((Any) -> String?)?
|
|
453
|
+
var exportingCondition: ((Any) -> Bool)?
|
|
454
|
+
var visibility = TransferRepresentationVisibility.all
|
|
455
|
+
|
|
456
|
+
/// A representation of the shim's own (SwiftUI's `Image`, whose bytes
|
|
457
|
+
/// know their type): `exporter` returns nil when it has nothing to give.
|
|
458
|
+
public init(exportType: UTType?, importType: UTType?, exporter: Exporter?, importer: Importer?) {
|
|
459
|
+
self.exportType = exportType
|
|
460
|
+
self.importType = importType
|
|
461
|
+
self.exporter = exporter
|
|
462
|
+
self.importer = importer
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
var exportedContentTypes: [UTType] {
|
|
466
|
+
guard exporter != nil else { return [] }
|
|
467
|
+
return proxyExportTypes?() ?? exportType.map { [$0] } ?? []
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
var importedContentTypes: [UTType] {
|
|
471
|
+
guard importer != nil else { return [] }
|
|
472
|
+
return proxyImportTypes?() ?? importType.map { [$0] } ?? []
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/// Whether this representation exports something `wanted` takes (anything, for nil).
|
|
476
|
+
func exports(_ wanted: UTType?) -> Bool {
|
|
477
|
+
guard exporter != nil else { return false }
|
|
478
|
+
guard let wanted else { return true }
|
|
479
|
+
return exportedContentTypes.contains { $0.conforms(to: wanted) }
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/// Whether this representation imports content of `type`.
|
|
483
|
+
func imports(_ type: UTType) -> Bool {
|
|
484
|
+
importedContentTypes.contains { type.conforms(to: $0) }
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/// A representation the shim builds from nodes directly.
|
|
489
|
+
public protocol _TransferPrimitive {
|
|
490
|
+
var _transferNodes: [_TransferNode] { get }
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
struct _UncheckedBox<Value>: @unchecked Sendable {
|
|
494
|
+
let value: Value
|
|
495
|
+
init(_ value: Value) { self.value = value }
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/// Walks representations: what sharing, item providers and pickers use.
|
|
499
|
+
public enum _Transfer {
|
|
500
|
+
/// A representation's nodes: its own, or its body's.
|
|
501
|
+
public static func nodes<R: TransferRepresentation>(of representation: R) -> [_TransferNode] {
|
|
502
|
+
if let primitive = representation as? any _TransferPrimitive { return primitive._transferNodes }
|
|
503
|
+
return nodes(of: representation.body)
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
public static func nodes<T: Transferable>(_ type: T.Type) -> [_TransferNode] {
|
|
507
|
+
nodes(of: T.transferRepresentation)
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
public static func exportedContentTypes<T: Transferable>(_ type: T.Type) -> [UTType] {
|
|
511
|
+
unique(nodes(type).flatMap(\.exportedContentTypes))
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
public static func importedContentTypes<T: Transferable>(_ type: T.Type) -> [UTType] {
|
|
515
|
+
unique(nodes(type).flatMap(\.importedContentTypes))
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/// Whether `type` imports content of `contentType`.
|
|
519
|
+
public static func canImport<T: Transferable>(_ type: T.Type, contentType: UTType) -> Bool {
|
|
520
|
+
nodes(type).contains { $0.imports(contentType) }
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/// The item's content from the first representation that exports
|
|
524
|
+
/// `wanted` (anything, for nil) and whose condition holds; nil if none does.
|
|
525
|
+
nonisolated(nonsending) public static func export<T: Transferable>(_ item: T, as wanted: UTType? = nil) async throws -> _TransferContent? {
|
|
526
|
+
// `String` and `URL` are leaves the page shares as text and links.
|
|
527
|
+
for node in nodes(T.self) where node.exports(wanted) {
|
|
528
|
+
if let condition = node.exportingCondition, !condition(item) { continue }
|
|
529
|
+
guard var content = try await node.exporter?(item, wanted) else { continue }
|
|
530
|
+
if let name = node.suggestedFileName?(item) {
|
|
531
|
+
content.suggestedName = (name as NSString).deletingPathExtension
|
|
532
|
+
}
|
|
533
|
+
if content.value == nil, wanted == nil, T.self == String.self || T.self == URL.self { content.value = item }
|
|
534
|
+
return content
|
|
535
|
+
}
|
|
536
|
+
return nil
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/// A value of `type` from `content`, through the first representation
|
|
540
|
+
/// that imports its content type; nil if none does.
|
|
541
|
+
nonisolated(nonsending) public static func `import`<T: Transferable>(_ type: T.Type, from content: _TransferContent) async throws -> T? {
|
|
542
|
+
for node in nodes(type) where node.imports(content.contentType) {
|
|
543
|
+
if let value = try await node.importer?(content) as? T { return value }
|
|
544
|
+
}
|
|
545
|
+
return nil
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
private static func unique(_ types: [UTType]) -> [UTType] {
|
|
549
|
+
var seen = Set<UTType>()
|
|
550
|
+
return types.filter { seen.insert($0).inserted }
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
// MARK: - Foundation's types
|
|
555
|
+
|
|
556
|
+
extension String: Transferable {
|
|
557
|
+
public static var transferRepresentation: _TransferRepresentationList<String> {
|
|
558
|
+
return _TransferRepresentationList(nodes: [
|
|
559
|
+
_TransferNode(exportType: .utf8PlainText, importType: .text,
|
|
560
|
+
exporter: { item, _ in _TransferContent(contentType: .utf8PlainText, data: Data((item as! String).utf8)) },
|
|
561
|
+
importer: { content in String(decoding: try content.loadData(), as: UTF8.self) }),
|
|
562
|
+
])
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
extension Data: Transferable {
|
|
567
|
+
public static var transferRepresentation: _TransferRepresentationList<Data> {
|
|
568
|
+
return _TransferRepresentationList(nodes: [
|
|
569
|
+
_TransferNode(exportType: .data, importType: .data,
|
|
570
|
+
exporter: { item, _ in _TransferContent(contentType: .data, data: item as? Data) },
|
|
571
|
+
importer: { content in try content.loadData() }),
|
|
572
|
+
])
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
extension URL: Transferable {
|
|
577
|
+
/// A link as `public.url` (its string), or a file as `public.file-url`.
|
|
578
|
+
public static var transferRepresentation: _TransferRepresentationList<URL> {
|
|
579
|
+
return _TransferRepresentationList(nodes: [
|
|
580
|
+
_TransferNode(exportType: .url, importType: .url,
|
|
581
|
+
exporter: { item, _ in
|
|
582
|
+
let url = item as! URL
|
|
583
|
+
return _TransferContent(contentType: url.isFileURL ? .fileURL : .url, data: Data(url.absoluteString.utf8))
|
|
584
|
+
},
|
|
585
|
+
importer: { content in
|
|
586
|
+
if content.contentType.conforms(to: .url), let data = content.data {
|
|
587
|
+
return URL(string: String(decoding: data, as: UTF8.self).trimmingCharacters(in: .whitespacesAndNewlines))
|
|
588
|
+
}
|
|
589
|
+
return content.file
|
|
590
|
+
}),
|
|
591
|
+
])
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
extension AttributedString: Transferable {
|
|
596
|
+
/// As its plain text: the browser's share sheet and clipboard take text.
|
|
597
|
+
public static var transferRepresentation: _TransferRepresentationList<AttributedString> {
|
|
598
|
+
return _TransferRepresentationList(nodes: [
|
|
599
|
+
_TransferNode(exportType: .utf8PlainText, importType: .text,
|
|
600
|
+
exporter: { item, _ in
|
|
601
|
+
_TransferContent(contentType: .utf8PlainText, data: Data(String((item as! AttributedString).characters).utf8))
|
|
602
|
+
},
|
|
603
|
+
importer: { content in AttributedString(String(decoding: try content.loadData(), as: UTF8.self)) }),
|
|
604
|
+
])
|
|
605
|
+
}
|
|
606
|
+
}
|