add aspect fill and update packages

This commit is contained in:
Ethan Pippin 2022-01-19 00:18:24 -07:00
parent 44229beee0
commit 45bafed1e9
5 changed files with 139 additions and 10 deletions

View File

@ -13,4 +13,19 @@ extension CGSize {
static func Circle(radius: CGFloat) -> CGSize {
CGSize(width: radius, height: radius)
}
// From https://gist.github.com/jkosoy/c835fea2c03e76720c77
static func aspectFill(aspectRatio: CGSize, minimumSize: CGSize) -> CGSize {
var minimumSize = minimumSize
let mW = minimumSize.width / aspectRatio.width
let mH = minimumSize.height / aspectRatio.height
if mH > mW {
minimumSize.width = minimumSize.height / aspectRatio.height * aspectRatio.width
} else if mW > mH {
minimumSize.height = minimumSize.width / aspectRatio.width * aspectRatio.height
}
return minimumSize
}
}

View File

@ -24,8 +24,8 @@
"repositoryURL": "https://github.com/CombineCommunity/CombineExt",
"state": {
"branch": null,
"revision": "8ca006df5e3cc6bb176b70238e2b0014bbc3a235",
"version": "1.0.0"
"revision": "0880829102152185190064fd17847a7c681d2127",
"version": "1.5.1"
}
},
{
@ -42,8 +42,8 @@
"repositoryURL": "https://github.com/sindresorhus/Defaults",
"state": {
"branch": null,
"revision": "8a6e4a96fd38504a05903d136c85634b65fd7c4d",
"version": "6.0.0"
"revision": "55f3302c3ab30a8760f10042d0ebc0a6907f865a",
"version": "6.1.0"
}
},
{
@ -96,8 +96,8 @@
"repositoryURL": "https://github.com/sushichop/Puppy",
"state": {
"branch": null,
"revision": "dc82e65c749cee431ffbb8c0913680b61ccd7e08",
"version": "0.2.0"
"revision": "95ce04b0e778b8d7c351876bc98bbf68328dfc9b",
"version": "0.3.1"
}
},
{
@ -105,8 +105,8 @@
"repositoryURL": "https://github.com/rundfunk47/stinsen",
"state": {
"branch": null,
"revision": "5e6c714f6f308877c8a988523915f9eb592d7d82",
"version": "2.0.3"
"revision": "36d97964075dc770046ddef9346a29bfa8982d6d",
"version": "2.0.7"
}
},
{

View File

@ -87,6 +87,8 @@ struct VLCPlayerOverlayView: View {
HStack(spacing: 20) {
// MARK: Previous Item
if viewModel.shouldShowPlayPreviousItem {
Button {
viewModel.playerOverlayDelegate?.didSelectPlayPreviousItem()
@ -97,6 +99,8 @@ struct VLCPlayerOverlayView: View {
.foregroundColor(viewModel.nextItemVideoPlayerViewModel == nil ? .gray : .white)
}
// MARK: Next Item
if viewModel.shouldShowPlayNextItem {
Button {
viewModel.playerOverlayDelegate?.didSelectPlayNextItem()
@ -107,6 +111,8 @@ struct VLCPlayerOverlayView: View {
.foregroundColor(viewModel.nextItemVideoPlayerViewModel == nil ? .gray : .white)
}
// MARK: Autoplay
if viewModel.shouldShowAutoPlay {
Button {
viewModel.autoplayEnabled.toggle()
@ -119,6 +125,8 @@ struct VLCPlayerOverlayView: View {
}
}
// MARK: Subtitle Toggle
if !viewModel.subtitleStreams.isEmpty {
Button {
viewModel.subtitlesEnabled.toggle()
@ -133,10 +141,32 @@ struct VLCPlayerOverlayView: View {
.foregroundColor(viewModel.selectedSubtitleStreamIndex == -1 ? .gray : .white)
}
// MARK: Screen Fill
Button {
viewModel.playerOverlayDelegate?.didSelectScreenFill()
} label: {
if viewModel.playerOverlayDelegate?.getScreenFilled() ?? true {
if viewModel.playerOverlayDelegate?.isVideoAspectRatioGreater() ?? true {
Image(systemName: "rectangle.arrowtriangle.2.inward")
} else {
Image(systemName: "rectangle.portrait.arrowtriangle.2.inward")
}
} else {
if viewModel.playerOverlayDelegate?.isVideoAspectRatioGreater() ?? true {
Image(systemName: "rectangle.arrowtriangle.2.outward")
} else {
Image(systemName: "rectangle.portrait.arrowtriangle.2.outward")
}
}
}
// MARK: Settings Menu
Menu {
// MARK: Audio Streams
Menu {
ForEach(viewModel.audioStreams, id: \.self) { audioStream in
Button {
@ -156,6 +186,8 @@ struct VLCPlayerOverlayView: View {
}
}
// MARK: Subtitle Streams
Menu {
ForEach(viewModel.subtitleStreams, id: \.self) { subtitleStream in
Button {
@ -175,6 +207,8 @@ struct VLCPlayerOverlayView: View {
}
}
// MARK: Playback Speed
Menu {
ForEach(PlaybackSpeed.allCases, id: \.self) { speed in
Button {
@ -194,6 +228,8 @@ struct VLCPlayerOverlayView: View {
}
}
// MARK: Chapters
if !viewModel.chapters.isEmpty {
Button {
viewModel.playerOverlayDelegate?.didSelectChapters()
@ -205,6 +241,8 @@ struct VLCPlayerOverlayView: View {
}
}
// MARK: Jump Button Lengths
if viewModel.shouldShowJumpButtonsInOverlayMenu {
Menu {
ForEach(VideoPlayerJumpLength.allCases, id: \.self) { forwardLength in

View File

@ -32,4 +32,10 @@ protocol PlayerOverlayDelegate {
func didSelectChapters()
func didSelectChapter(_ chapter: ChapterInfo)
func didSelectScreenFill()
func getScreenFilled() -> Bool
// Returns whether the aspect ratio of the video
// is greater than the aspect ratio of the screen
func isVideoAspectRatioGreater() -> Bool
}

View File

@ -28,6 +28,7 @@ class VLCPlayerViewController: UIViewController {
private var lastProgressReportTicks: Int64 = 0
private var viewModelListeners = Set<AnyCancellable>()
private var overlayDismissTimer: Timer?
private var isScreenFilled: Bool = false
private var currentPlayerTicks: Int64 {
Int64(vlcMediaPlayer.time.intValue) * 100_000
@ -42,7 +43,7 @@ class VLCPlayerViewController: UIViewController {
}
private lazy var videoContentView = makeVideoContentView()
private lazy var mainGestureView = makeTapGestureView()
private lazy var mainGestureView = makeMainGestureView()
private var currentOverlayHostingController: UIHostingController<VLCPlayerOverlayView>?
private var currentChapterOverlayHostingController: UIHostingController<VLCPlayerChapterOverlayView>?
private var currentJumpBackwardOverlayView: UIImageView?
@ -152,7 +153,7 @@ class VLCPlayerViewController: UIViewController {
return view
}
private func makeTapGestureView() -> UIView {
private func makeMainGestureView() -> UIView {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
@ -164,7 +165,10 @@ class VLCPlayerViewController: UIViewController {
let leftSwipeGesture = UISwipeGestureRecognizer(target: self, action: #selector(didLeftSwipe))
leftSwipeGesture.direction = .left
let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(didPinch(_:)))
view.addGestureRecognizer(singleTapGesture)
view.addGestureRecognizer(pinchGesture)
if viewModel.jumpGesturesEnabled {
view.addGestureRecognizer(rightSwipeGesture)
@ -189,6 +193,23 @@ class VLCPlayerViewController: UIViewController {
self.didSelectBackward()
}
private var pinchScale: CGFloat = 1
@objc
private func didPinch(_ gestureRecognizer: UIPinchGestureRecognizer) {
if gestureRecognizer.state == .began || gestureRecognizer.state == .changed {
pinchScale = gestureRecognizer.scale
} else {
isScreenFilled.toggle()
if pinchScale > 1 {
fillScreen()
} else {
shrinkScreen()
}
}
}
// MARK: setupOverlayHostingController
private func setupOverlayHostingController(viewModel: VideoPlayerViewModel) {
@ -814,4 +835,53 @@ extension VLCPlayerViewController: PlayerOverlayDelegate {
viewModel.sendProgressReport()
}
func didSelectScreenFill() {
isScreenFilled.toggle()
if isScreenFilled {
fillScreen()
} else {
shrinkScreen()
}
}
private func fillScreen() {
let screenSize = UIScreen.main.bounds.size
let videoSize = vlcMediaPlayer.videoSize
let fillSize = CGSize.aspectFill(aspectRatio: videoSize, minimumSize: screenSize)
let scale: CGFloat
if fillSize.height > screenSize.height {
scale = fillSize.height / screenSize.height
} else {
scale = fillSize.width / screenSize.width
}
UIView.animate(withDuration: 0.2) {
self.videoContentView.transform = CGAffineTransform(scaleX: scale, y: scale)
}
}
private func shrinkScreen() {
UIView.animate(withDuration: 0.2) {
self.videoContentView.transform = .identity
}
}
func getScreenFilled() -> Bool {
isScreenFilled
}
func isVideoAspectRatioGreater() -> Bool {
let screenSize = UIScreen.main.bounds.size
let videoSize = vlcMediaPlayer.videoSize
let screenAspectRatio = screenSize.width / screenSize.height
let videoAspectRatio = videoSize.width / videoSize.height
return videoAspectRatio > screenAspectRatio
}
}