WebView.swift 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. import Foundation
  2. /// A web view.
  3. @available(tvOS, unavailable)
  4. public struct WebView: ElementaryView {
  5. /// The ideal size of a WebView.
  6. private static let idealSize = ViewSize(10, 10)
  7. @State var currentURL: URL?
  8. @Binding var url: URL
  9. /// Creates a web view.
  10. ///
  11. /// - Parameter url: A binding to the web view's URL.
  12. public init(_ url: Binding<URL>) {
  13. _url = url
  14. }
  15. func asWidget<Backend: BaseAppBackend>(backend: Backend) -> Backend.Widget {
  16. func castBackend_inner<NewBackend: BaseAppBackend & BackendFeatures.WebViews>(_ backend: NewBackend) -> NewBackend.Widget {
  17. return backend.createWebView()
  18. }
  19. guard let castedBackend = backend as? any (BaseAppBackend & BackendFeatures.WebViews) else {
  20. fatalError("Backend does not implement BackendFeatures.WebViews")
  21. }
  22. return castBackend_inner(castedBackend) as! Backend.Widget
  23. }
  24. func computeLayout<Backend: BaseAppBackend>(
  25. _ widget: Backend.Widget,
  26. proposedSize: ProposedViewSize,
  27. environment: EnvironmentValues,
  28. backend: Backend
  29. ) -> ViewLayoutResult {
  30. let size = proposedSize.replacingUnspecifiedDimensions(by: Self.idealSize)
  31. return ViewLayoutResult.leafView(size: size)
  32. }
  33. func commit<Backend: BaseAppBackend>(
  34. _ widget: Backend.Widget,
  35. layout: ViewLayoutResult,
  36. environment: EnvironmentValues,
  37. backend: Backend
  38. ) {
  39. func castBackend_inner<NewBackend: BaseAppBackend & BackendFeatures.WebViews>(_ backend: NewBackend) {
  40. let widget = widget as! NewBackend.Widget
  41. if url != currentURL {
  42. backend.navigateWebView(widget, to: url)
  43. currentURL = url
  44. }
  45. backend.updateWebView(widget, environment: environment) { destination in
  46. currentURL = destination
  47. url = destination
  48. }
  49. backend.setSize(of: widget, to: layout.size.vector)
  50. }
  51. guard let castedBackend = backend as? any (BaseAppBackend & BackendFeatures.WebViews) else {
  52. fatalError("Backend does not implement BackendFeatures.WebViews")
  53. }
  54. castBackend_inner(castedBackend)
  55. }
  56. }