@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,363 @@
|
|
|
1
|
+
// `UIPasteboard` in the browser. A page cannot read the system clipboard
|
|
2
|
+
// without asking the viewer each time (and never synchronously), so the
|
|
3
|
+
// pasteboard keeps its items in memory, as an app-private pasteboard would:
|
|
4
|
+
// what the app put there, it reads back. Writing also copies to the system
|
|
5
|
+
// clipboard through the page (a `clipboard` host request: the Async
|
|
6
|
+
// Clipboard API's `writeText`, or an `image/png` item for an image), so the
|
|
7
|
+
// viewer can paste a copied link or picture in another app. Text the viewer
|
|
8
|
+
// pastes into a text field or editor is the browser's own paste, which needs
|
|
9
|
+
// none of this (docs/ops-protocol.md, "Sharing and media").
|
|
10
|
+
|
|
11
|
+
// On iOS, UIKit brings UniformTypeIdentifiers along (`UTType.jpeg` with
|
|
12
|
+
// only `import UIKit`).
|
|
13
|
+
@_exported import UniformTypeIdentifiers
|
|
14
|
+
import Foundation
|
|
15
|
+
import FoundationBridge
|
|
16
|
+
import SwiftUI
|
|
17
|
+
|
|
18
|
+
/// The system clipboard, through the page.
|
|
19
|
+
@MainActor
|
|
20
|
+
public enum _PageClipboard {
|
|
21
|
+
/// Copies `fields` (`text`, or a picture's `files` / `bitmaps` / `images`)
|
|
22
|
+
/// to the system clipboard. The answer is not awaited by the app: the
|
|
23
|
+
/// browser may refuse (no focus, no permission), and the in-memory
|
|
24
|
+
/// pasteboard has the items either way.
|
|
25
|
+
public static func write(_ fields: [String: _JSON]) {
|
|
26
|
+
guard !fields.isEmpty else { return }
|
|
27
|
+
var params = fields
|
|
28
|
+
params["action"] = .string("write")
|
|
29
|
+
Task { @MainActor in
|
|
30
|
+
_ = try? await _PageFiles.hostRequest("clipboard", .object(params), .object([:]))
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/// Reads the system clipboard's text (the browser may ask the viewer
|
|
35
|
+
/// first, or refuse); nil when there is none or the page could not read it.
|
|
36
|
+
public static func readText() async -> String? {
|
|
37
|
+
guard let answer = try? await _PageFiles.hostRequest("clipboard", .object(["action": .string("readText")]), .object([:])),
|
|
38
|
+
case .object(let fields) = answer, case .string(let text)? = fields["text"] else { return nil }
|
|
39
|
+
return text
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/// A pasteboard: the general one (also copied to the system clipboard) or a
|
|
44
|
+
/// named one, private to the app. Items are dictionaries from type
|
|
45
|
+
/// identifiers to values (strings, URLs, images, data), as on iOS.
|
|
46
|
+
open class UIPasteboard: @unchecked Sendable {
|
|
47
|
+
public struct Name: RawRepresentable, Hashable, Sendable {
|
|
48
|
+
public let rawValue: String
|
|
49
|
+
public init(rawValue: String) { self.rawValue = rawValue }
|
|
50
|
+
public init(_ rawValue: String) { self.rawValue = rawValue }
|
|
51
|
+
public static let general = Name("com.apple.UIKit.pboard.general")
|
|
52
|
+
@available(*, deprecated)
|
|
53
|
+
public static let find = Name("com.apple.UIKit.pboard.find")
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
public struct OptionsKey: RawRepresentable, Hashable, Sendable {
|
|
57
|
+
public let rawValue: String
|
|
58
|
+
public init(rawValue: String) { self.rawValue = rawValue }
|
|
59
|
+
public static let localOnly = OptionsKey(rawValue: "com.apple.UIKit.pboard.localOnly")
|
|
60
|
+
public static let expirationDate = OptionsKey(rawValue: "com.apple.UIKit.pboard.expirationDate")
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
public static let changedNotification = Notification.Name("UIPasteboardChangedNotification")
|
|
64
|
+
public static let removedNotification = Notification.Name("UIPasteboardRemovedNotification")
|
|
65
|
+
public static let changedTypesAddedUserInfoKey = "UIPasteboardChangedTypesAddedKey"
|
|
66
|
+
public static let changedTypesRemovedUserInfoKey = "UIPasteboardChangedTypesRemovedKey"
|
|
67
|
+
|
|
68
|
+
public static let typeListString: [String] = [UTType.utf8PlainText.identifier, UTType.plainText.identifier, UTType.text.identifier]
|
|
69
|
+
public static let typeListURL: [String] = [UTType.url.identifier]
|
|
70
|
+
public static let typeListImage: [String] = [UTType.png.identifier, UTType.jpeg.identifier, UTType.gif.identifier, UTType.image.identifier]
|
|
71
|
+
public static let typeListColor: [String] = ["com.apple.uikit.color"]
|
|
72
|
+
public static let typeAutomatic = "com.apple.uikit.pasteboard.automatic"
|
|
73
|
+
|
|
74
|
+
nonisolated(unsafe) private static var named: [Name: UIPasteboard] = [:]
|
|
75
|
+
|
|
76
|
+
/// The general pasteboard: what the app copies also goes to the system clipboard.
|
|
77
|
+
public static var general: UIPasteboard { pasteboard(.general) }
|
|
78
|
+
|
|
79
|
+
public let name: Name
|
|
80
|
+
open var isPersistent = false
|
|
81
|
+
public private(set) var changeCount = 0
|
|
82
|
+
private var storage: [[String: Any]] = []
|
|
83
|
+
|
|
84
|
+
init(name: Name) { self.name = name }
|
|
85
|
+
|
|
86
|
+
private static func pasteboard(_ name: Name) -> UIPasteboard {
|
|
87
|
+
if let existing = named[name] { return existing }
|
|
88
|
+
let pasteboard = UIPasteboard(name: name)
|
|
89
|
+
named[name] = pasteboard
|
|
90
|
+
return pasteboard
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/// A named pasteboard, private to the app; nil when it does not exist and `create` is false.
|
|
94
|
+
public convenience init?(name pasteboardName: Name, create: Bool) {
|
|
95
|
+
guard create || Self.named[pasteboardName] != nil else { return nil }
|
|
96
|
+
self.init(name: pasteboardName)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public static func withUniqueName() -> UIPasteboard { pasteboard(Name(UUID().uuidString)) }
|
|
100
|
+
|
|
101
|
+
public static func remove(withName pasteboardName: Name) { named[pasteboardName] = nil }
|
|
102
|
+
|
|
103
|
+
// MARK: Items
|
|
104
|
+
|
|
105
|
+
/// The items, each a dictionary from type identifiers to values.
|
|
106
|
+
open var items: [[String: Any]] {
|
|
107
|
+
get { storage }
|
|
108
|
+
set { setItems(newValue) }
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
open func setItems(_ items: [[String: Any]], options: [OptionsKey: Any] = [:]) {
|
|
112
|
+
storage = items
|
|
113
|
+
changed()
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
open func addItems(_ items: [[String: Any]]) {
|
|
117
|
+
storage += items
|
|
118
|
+
changed()
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
open var numberOfItems: Int { storage.count }
|
|
122
|
+
|
|
123
|
+
/// The types of the first item.
|
|
124
|
+
open var types: [String] { storage.first.map { Array($0.keys) } ?? [] }
|
|
125
|
+
|
|
126
|
+
open func types(forItemSet itemSet: IndexSet?) -> [[String]]? {
|
|
127
|
+
indices(itemSet).map { Array(storage[$0].keys) }
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
open func contains(pasteboardTypes: [String]) -> Bool {
|
|
131
|
+
storage.contains { item in item.keys.contains { key in pasteboardTypes.contains { Self.conforms(key, to: $0) } } }
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
open func contains(pasteboardTypes: [String], inItemSet itemSet: IndexSet?) -> Bool {
|
|
135
|
+
indices(itemSet).contains { index in storage[index].keys.contains { key in pasteboardTypes.contains { Self.conforms(key, to: $0) } } }
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
open func data(forPasteboardType pasteboardType: String) -> Data? {
|
|
139
|
+
guard let value = value(forPasteboardType: pasteboardType) else { return nil }
|
|
140
|
+
switch value {
|
|
141
|
+
case let data as Data: return data
|
|
142
|
+
case let string as String: return Data(string.utf8)
|
|
143
|
+
case let url as URL: return Data(url.absoluteString.utf8)
|
|
144
|
+
case let image as UIImage: return image._encodedFile?.data
|
|
145
|
+
default: return nil
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
open func setData(_ data: Data, forPasteboardType pasteboardType: String) {
|
|
150
|
+
storage = [[pasteboardType: data]]
|
|
151
|
+
changed()
|
|
152
|
+
if UTType(pasteboardType)?.conforms(to: .text) == true {
|
|
153
|
+
copyValueToSystem(String(decoding: data, as: UTF8.self))
|
|
154
|
+
} else if let image = UIImage(data: data) {
|
|
155
|
+
copyValueToSystem(image)
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/// The first item's value for a type (or a type conforming to it).
|
|
160
|
+
open func value(forPasteboardType pasteboardType: String) -> Any? {
|
|
161
|
+
guard let first = storage.first else { return nil }
|
|
162
|
+
if let value = first[pasteboardType] { return value }
|
|
163
|
+
return first.first { Self.conforms($0.key, to: pasteboardType) }?.value
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
open func setValue(_ value: Any, forPasteboardType pasteboardType: String) {
|
|
167
|
+
storage = [[pasteboardType: value]]
|
|
168
|
+
changed()
|
|
169
|
+
copyValueToSystem(value)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
open func data(forPasteboardType pasteboardType: String, inItemSet itemSet: IndexSet?) -> [Data]? {
|
|
173
|
+
let found = indices(itemSet).compactMap { storage[$0][pasteboardType] as? Data }
|
|
174
|
+
return found.isEmpty ? nil : found
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
open func values(forPasteboardType pasteboardType: String, inItemSet itemSet: IndexSet?) -> [Any]? {
|
|
178
|
+
let found = indices(itemSet).compactMap { storage[$0][pasteboardType] }
|
|
179
|
+
return found.isEmpty ? nil : found
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// MARK: Item providers
|
|
183
|
+
|
|
184
|
+
/// An item provider per item, offering its values.
|
|
185
|
+
open var itemProviders: [NSItemProvider] {
|
|
186
|
+
get {
|
|
187
|
+
storage.map { item in
|
|
188
|
+
let provider = NSItemProvider()
|
|
189
|
+
for (key, value) in item {
|
|
190
|
+
if let object = value as? any NSItemProviderWriting {
|
|
191
|
+
provider.registerObject(object, visibility: .all)
|
|
192
|
+
} else {
|
|
193
|
+
let box = _PasteboardValue(value)
|
|
194
|
+
provider.registerDataRepresentation(forTypeIdentifier: key, visibility: .all) { completion in
|
|
195
|
+
completion(box.data, nil)
|
|
196
|
+
return nil
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return provider
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
set { setItemProviders(newValue, localOnly: false, expirationDate: nil) }
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/// Takes the providers' objects: what each offers as text, a URL or an
|
|
207
|
+
/// image is loaded and becomes an item, in order, when loaded.
|
|
208
|
+
open func setItemProviders(_ itemProviders: [NSItemProvider], localOnly: Bool, expirationDate: Date?) {
|
|
209
|
+
storage = []
|
|
210
|
+
changed()
|
|
211
|
+
for provider in itemProviders {
|
|
212
|
+
if provider.canLoadObject(ofClass: UIImage.self) {
|
|
213
|
+
provider.loadObject(ofClass: UIImage.self) { [weak self] image, _ in
|
|
214
|
+
guard let image else { return }
|
|
215
|
+
Task { @MainActor in self?.image = image }
|
|
216
|
+
}
|
|
217
|
+
} else if provider.canLoadObject(ofClass: URL.self) {
|
|
218
|
+
provider.loadObject(ofClass: URL.self) { [weak self] url, _ in
|
|
219
|
+
guard let url else { return }
|
|
220
|
+
Task { @MainActor in self?.url = url }
|
|
221
|
+
}
|
|
222
|
+
} else if provider.canLoadObject(ofClass: String.self) {
|
|
223
|
+
provider.loadObject(ofClass: String.self) { [weak self] string, _ in
|
|
224
|
+
guard let string else { return }
|
|
225
|
+
Task { @MainActor in self?.string = string }
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
open func setObjects<T: NSItemProviderWriting>(_ objects: [T]) {
|
|
232
|
+
setObjects(objects, localOnly: false, expirationDate: nil)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
open func setObjects<T: NSItemProviderWriting>(_ objects: [T], localOnly: Bool, expirationDate: Date?) {
|
|
236
|
+
storage = objects.map { object in
|
|
237
|
+
Dictionary(object.writableTypeIdentifiersForItemProvider.map { ($0, object as Any) }, uniquingKeysWith: { first, _ in first })
|
|
238
|
+
}
|
|
239
|
+
changed()
|
|
240
|
+
if let first = objects.first { copyValueToSystem(first) }
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// MARK: Strings, URLs, images, colors
|
|
244
|
+
|
|
245
|
+
/// The first text item, or the first URL as text (as iOS coerces it).
|
|
246
|
+
open var string: String? {
|
|
247
|
+
get { strings?.first }
|
|
248
|
+
set { set(newValue.map { [$0] } ?? [], type: UTType.utf8PlainText.identifier) }
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
open var strings: [String]? {
|
|
252
|
+
get {
|
|
253
|
+
let found = storage.compactMap { item -> String? in
|
|
254
|
+
if let text = Self.typeListString.lazy.compactMap({ item[$0] as? String }).first { return text }
|
|
255
|
+
return (item[UTType.url.identifier] as? URL)?.absoluteString
|
|
256
|
+
}
|
|
257
|
+
return found.isEmpty ? nil : found
|
|
258
|
+
}
|
|
259
|
+
set { set(newValue ?? [], type: UTType.utf8PlainText.identifier) }
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
open var url: URL? {
|
|
263
|
+
get { urls?.first }
|
|
264
|
+
set { set(newValue.map { [$0] } ?? [], type: UTType.url.identifier) }
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
open var urls: [URL]? {
|
|
268
|
+
get {
|
|
269
|
+
let found = storage.compactMap { item -> URL? in
|
|
270
|
+
if let url = item[UTType.url.identifier] as? URL { return url }
|
|
271
|
+
return Self.typeListString.lazy.compactMap { item[$0] as? String }.first.flatMap { URL(string: $0) }.flatMap { $0.scheme == nil ? nil : $0 }
|
|
272
|
+
}
|
|
273
|
+
return found.isEmpty ? nil : found
|
|
274
|
+
}
|
|
275
|
+
set { set(newValue ?? [], type: UTType.url.identifier) }
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
open var image: UIImage? {
|
|
279
|
+
get { images?.first }
|
|
280
|
+
set { set(newValue.map { [$0] } ?? [], type: UTType.png.identifier) }
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
open var images: [UIImage]? {
|
|
284
|
+
get {
|
|
285
|
+
let found = storage.compactMap { item in item.values.lazy.compactMap { $0 as? UIImage }.first }
|
|
286
|
+
return found.isEmpty ? nil : found
|
|
287
|
+
}
|
|
288
|
+
set { set(newValue ?? [], type: UTType.png.identifier) }
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
open var color: UIColor? {
|
|
292
|
+
get { colors?.first }
|
|
293
|
+
set { set(newValue.map { [$0] } ?? [], type: Self.typeListColor[0]) }
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
open var colors: [UIColor]? {
|
|
297
|
+
get {
|
|
298
|
+
let found = storage.compactMap { item in item.values.lazy.compactMap { $0 as? UIColor }.first }
|
|
299
|
+
return found.isEmpty ? nil : found
|
|
300
|
+
}
|
|
301
|
+
set { set(newValue ?? [], type: Self.typeListColor[0]) }
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
open var hasStrings: Bool { strings != nil }
|
|
305
|
+
open var hasURLs: Bool { urls != nil }
|
|
306
|
+
open var hasImages: Bool { images != nil }
|
|
307
|
+
open var hasColors: Bool { colors != nil }
|
|
308
|
+
|
|
309
|
+
// MARK: Helpers
|
|
310
|
+
|
|
311
|
+
private func set(_ values: [Any], type: String) {
|
|
312
|
+
storage = values.map { [type: $0] }
|
|
313
|
+
changed()
|
|
314
|
+
if let first = values.first { copyValueToSystem(first) }
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
private func changed() {
|
|
318
|
+
changeCount += 1
|
|
319
|
+
FoundationBridge.NotificationCenter.default.post(name: Self.changedNotification, object: self)
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/// Copies a string, URL or image to the system clipboard: only the
|
|
323
|
+
/// general pasteboard's, from a task on the main actor (which the
|
|
324
|
+
/// browser runs right after the tap that copied, so the page still has
|
|
325
|
+
/// the viewer's activation).
|
|
326
|
+
private func copyValueToSystem(_ value: Any) {
|
|
327
|
+
guard name == .general else { return }
|
|
328
|
+
let box = _PasteboardValue(value)
|
|
329
|
+
Task { @MainActor in
|
|
330
|
+
switch box.value {
|
|
331
|
+
case let string as String: _PageClipboard.write(["text": .string(string)])
|
|
332
|
+
case let url as URL: _PageClipboard.write(["text": .string(url.absoluteString)])
|
|
333
|
+
case let image as UIImage: _PageClipboard.write(_PageFiles.fields(for: image, name: "Image"))
|
|
334
|
+
default: break
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
private func indices(_ itemSet: IndexSet?) -> [Int] {
|
|
340
|
+
guard let itemSet else { return Array(storage.indices) }
|
|
341
|
+
return itemSet.filter { storage.indices.contains($0) }
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
private static func conforms(_ identifier: String, to other: String) -> Bool {
|
|
345
|
+
if identifier == other { return true }
|
|
346
|
+
guard let type = UTType(identifier), let otherType = UTType(other) else { return false }
|
|
347
|
+
return type.conforms(to: otherType)
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
private struct _PasteboardValue: @unchecked Sendable {
|
|
352
|
+
let value: Any
|
|
353
|
+
init(_ value: Any) { self.value = value }
|
|
354
|
+
var data: Data? {
|
|
355
|
+
switch value {
|
|
356
|
+
case let data as Data: data
|
|
357
|
+
case let string as String: Data(string.utf8)
|
|
358
|
+
case let url as URL: Data(url.absoluteString.utf8)
|
|
359
|
+
case let image as UIImage: image._encodedFile?.data
|
|
360
|
+
default: nil
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// Saving to the photo album, in the browser: the page has no photo library,
|
|
2
|
+
// so a saved image or video becomes a download (a `download` host request;
|
|
3
|
+
// docs/ops-protocol.md, "Sharing and media"). The browser puts it in the
|
|
4
|
+
// viewer's downloads folder, or asks where to, as it does for any download.
|
|
5
|
+
// Photos' `PHAssetChangeRequest` saves the same way (Sources/Photos).
|
|
6
|
+
|
|
7
|
+
import Foundation
|
|
8
|
+
import FoundationBridge
|
|
9
|
+
import SwiftUI
|
|
10
|
+
|
|
11
|
+
/// Files the app hands to the page: to download (`download`), share
|
|
12
|
+
/// (`share`) or copy (`clipboard`). Used by UIKit, Photos and LinkPresentation.
|
|
13
|
+
@MainActor
|
|
14
|
+
public enum _PageFiles {
|
|
15
|
+
/// The request fields that carry `image`: `files` for an image made from
|
|
16
|
+
/// a file (its own bytes), `bitmaps` for one the page draws from a recipe
|
|
17
|
+
/// (Core Image, a drawing; the page encodes it as PNG), `images` for an
|
|
18
|
+
/// asset-catalog image. Empty for a symbol or an empty image.
|
|
19
|
+
public static func fields(for image: UIImage, name: String) -> [String: _JSON] {
|
|
20
|
+
if let file = image._encodedFile {
|
|
21
|
+
let ext = UTType(mimeType: file.mime)?.preferredFilenameExtension ?? "png"
|
|
22
|
+
return ["files": .array([entry(name: "\(name).\(ext)", type: file.mime, data: file.data)])]
|
|
23
|
+
}
|
|
24
|
+
if let recipe = image._recipe, let source = recipe.source {
|
|
25
|
+
_Runtime.shared._sendImageSource(source)
|
|
26
|
+
return ["bitmaps": .array([recipe._json])]
|
|
27
|
+
}
|
|
28
|
+
if let catalogName = image._catalogName { return ["images": .array([.string(catalogName)])] }
|
|
29
|
+
return [:]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/// The `files` entry for a file's bytes.
|
|
33
|
+
public static func entry(name: String, type: String, data: Data) -> _JSON {
|
|
34
|
+
.object(["name": .string(name), "type": .string(type), "data": .string(_base64([UInt8](data)))])
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/// The `files` entry for the file at `url`, typed by its extension.
|
|
38
|
+
public static func entry(fileURL url: URL) throws -> _JSON {
|
|
39
|
+
let type = UTType(filenameExtension: url.pathExtension)?.preferredMIMEType ?? "application/octet-stream"
|
|
40
|
+
return entry(name: url.lastPathComponent, type: type, data: try Data(contentsOf: url))
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/// Asks the page to download what `fields` carry (`title` names bitmap
|
|
44
|
+
/// files). Headless runs answer at once; the op in the log is the record.
|
|
45
|
+
public static func download(_ fields: [String: _JSON], title: String) async throws {
|
|
46
|
+
guard !fields.isEmpty else { throw CocoaError(.fileWriteUnknown) }
|
|
47
|
+
var params = fields
|
|
48
|
+
params["title"] = .string(title)
|
|
49
|
+
_ = try await hostRequest("download", .object(params), .object(["outcome": .string("headless")]))
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/// Sends a host request (kind, params, headless answer); tests replace it.
|
|
53
|
+
public static var hostRequest: @MainActor (String, _JSON, _JSON) async throws -> _JSON = { kind, params, headless in
|
|
54
|
+
try await _Runtime.shared._hostRequest(kind: kind, params: params, headless: headless)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/// Saves `image` to the photo album: in the browser, downloads it (its own
|
|
59
|
+
/// file for an image made from data, else a PNG the page draws). The
|
|
60
|
+
/// completion selector is not called (the browser's Swift cannot call a
|
|
61
|
+
/// three-argument selector); the download happens or fails on its own.
|
|
62
|
+
public func UIImageWriteToSavedPhotosAlbum(_ image: UIImage, _ completionTarget: Any?, _ completionSelector: Selector?,
|
|
63
|
+
_ contextInfo: UnsafeMutableRawPointer?) {
|
|
64
|
+
Task { @MainActor in
|
|
65
|
+
try? await _PageFiles.download(_PageFiles.fields(for: image, name: "Photo"), title: "Photo")
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/// Whether the video at `videoPath` can be saved: any file that exists.
|
|
70
|
+
public func UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(_ videoPath: String) -> Bool {
|
|
71
|
+
FileManager.default.fileExists(atPath: videoPath)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/// Saves the video at `videoPath` to the photo album: in the browser, downloads the file.
|
|
75
|
+
public func UISaveVideoAtPathToSavedPhotosAlbum(_ videoPath: String, _ completionTarget: Any?, _ completionSelector: Selector?,
|
|
76
|
+
_ contextInfo: UnsafeMutableRawPointer?) {
|
|
77
|
+
Task { @MainActor in
|
|
78
|
+
guard let entry = try? _PageFiles.entry(fileURL: URL(fileURLWithPath: videoPath)) else { return }
|
|
79
|
+
try? await _PageFiles.download(["files": .array([entry])], title: "Video")
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Remote (APNs) notification registration. The browser has no APNs: Apple
|
|
2
|
+
// never hands the page a device token, so registering does nothing and the
|
|
3
|
+
// app delegate's `didRegisterForRemoteNotificationsWithDeviceToken` is never
|
|
4
|
+
// called, which apps already handle (a simulator behaves the same). Local
|
|
5
|
+
// notifications are UserNotifications' (docs/ops-protocol.md, "Notifications").
|
|
6
|
+
|
|
7
|
+
import Foundation
|
|
8
|
+
|
|
9
|
+
extension UIApplication {
|
|
10
|
+
/// Does nothing: no device token ever arrives.
|
|
11
|
+
public func registerForRemoteNotifications() {}
|
|
12
|
+
public func unregisterForRemoteNotifications() {}
|
|
13
|
+
/// False: the page never gets a device token.
|
|
14
|
+
public var isRegisteredForRemoteNotifications: Bool { false }
|
|
15
|
+
}
|