VideoPlayView.swift 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. //
  2. // VideoPlayView.swift
  3. // LoopKitUI
  4. //
  5. // Created by Rick Pasetto on 5/12/22.
  6. // Copyright © 2022 LoopKit Authors. All rights reserved.
  7. //
  8. import SwiftUI
  9. public struct VideoPlayView<ThumbnailContent: View>: View {
  10. let thumbnail: () -> ThumbnailContent
  11. let includeThumbnailBorder: Bool
  12. let centerThumbnail: Bool
  13. let url: URL?
  14. let hasBeenPlayed: Binding<Bool>
  15. private var _autoPlay: Bool = true
  16. private var _overrideMuteSwitch: Bool = true
  17. // This from right out of the Design spec
  18. private let frameColor = Color(UIColor(red: 0.784, green: 0.784, blue: 0.784, alpha: 1))
  19. public init(url: URL?, thumbnail: @autoclosure @escaping () -> ThumbnailContent, includeThumbnailBorder: Bool = true, centerThumbnail: Bool = true) {
  20. self.url = url
  21. self.thumbnail = thumbnail
  22. self.includeThumbnailBorder = includeThumbnailBorder
  23. self.centerThumbnail = centerThumbnail
  24. self.hasBeenPlayed = .false
  25. }
  26. public init(url: URL?, thumbnail: @autoclosure @escaping () -> ThumbnailContent, hasBeenPlayed: Binding<Bool>, includeThumbnailBorder: Bool = true, centerThumbnail: Bool = true) {
  27. self.url = url
  28. self.thumbnail = thumbnail
  29. self.includeThumbnailBorder = includeThumbnailBorder
  30. self.centerThumbnail = centerThumbnail
  31. self.hasBeenPlayed = hasBeenPlayed
  32. }
  33. private init(_ other: Self, url: URL?? = nil, thumbnail: (() -> ThumbnailContent)? = nil, hasBeenPlayed: Binding<Bool>? = nil, autoPlay: Bool? = nil, overrideMuteSwitch: Bool? = nil, includeThumbnailBorder: Bool? = nil, centerThumbnail: Bool? = nil) {
  34. self.url = url ?? other.url
  35. self.thumbnail = thumbnail ?? other.thumbnail
  36. self.hasBeenPlayed = hasBeenPlayed ?? other.hasBeenPlayed
  37. self.includeThumbnailBorder = includeThumbnailBorder ?? other.includeThumbnailBorder
  38. self.centerThumbnail = centerThumbnail ?? other.centerThumbnail
  39. self._autoPlay = autoPlay ?? other._autoPlay
  40. self._overrideMuteSwitch = overrideMuteSwitch ?? other._overrideMuteSwitch
  41. }
  42. public var body: some View {
  43. PopoverLink(destination: videoView) {
  44. if includeThumbnailBorder {
  45. placeholderImage
  46. .padding()
  47. .border(frameColor, width: 1)
  48. } else {
  49. placeholderImage
  50. }
  51. }
  52. .fullScreen()
  53. }
  54. private var placeholderImage: some View {
  55. HStack {
  56. if centerThumbnail {
  57. Spacer()
  58. }
  59. ZStack {
  60. thumbnail()
  61. Image(frameworkImage: "play-button", decorative: true)
  62. }
  63. if centerThumbnail {
  64. Spacer()
  65. }
  66. }
  67. .aspectRatio(CGSize(width: 16, height: 9), contentMode: .fit)
  68. .frame(maxWidth: .infinity)
  69. }
  70. @ViewBuilder
  71. private var videoView: some View {
  72. VideoView(url: url, autoPlay: _autoPlay, overrideMuteSwitch: _overrideMuteSwitch)
  73. .onDisappear { hasBeenPlayed.wrappedValue = true }
  74. }
  75. public func autoPlay(_ enabled: Bool) -> Self {
  76. Self.init(self, autoPlay: enabled)
  77. }
  78. public func overrideMuteSwitch(_ enabled: Bool) -> Self {
  79. Self.init(self, overrideMuteSwitch: enabled)
  80. }
  81. public func includeThumbnailBorder(_ value: Bool) -> Self {
  82. Self.init(self, includeThumbnailBorder: value)
  83. }
  84. public func centerThumbnail(_ value: Bool) -> Self {
  85. Self.init(self, centerThumbnail: value)
  86. }
  87. }
  88. fileprivate extension Binding where Value == Bool {
  89. static var `true` = Binding(get: { true }, set: { _ in })
  90. static var `false` = Binding(get: { false }, set: { _ in })
  91. }