diff --git a/Persephone.xcodeproj/project.pbxproj b/Persephone.xcodeproj/project.pbxproj index c800623..5de1286 100644 --- a/Persephone.xcodeproj/project.pbxproj +++ b/Persephone.xcodeproj/project.pbxproj @@ -8,6 +8,8 @@ /* Begin PBXBuildFile section */ 38BAC36B249CB1A7004BAEA4 /* AlbumDetailSongTitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38BAC36A249CB1A6004BAEA4 /* AlbumDetailSongTitleView.swift */; }; + E403E63E246F4C3900200F58 /* NowPlayingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E403E63C246F4C3900200F58 /* NowPlayingViewController.swift */; }; + E403E63F246F4C3900200F58 /* NowPlayingViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = E403E63D246F4C3900200F58 /* NowPlayingViewController.xib */; }; E407861C2110CE6E006887B1 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E407861B2110CE6E006887B1 /* AppDelegate.swift */; }; E40786202110CE70006887B1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E407861F2110CE70006887B1 /* Assets.xcassets */; }; E40786232110CE70006887B1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E40786212110CE70006887B1 /* Main.storyboard */; }; @@ -320,6 +322,9 @@ E4F2EFEE24076A2700198159 /* ServerState.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F2EFED24076A2700198159 /* ServerState.swift */; }; E4F2EFF024076B0900198159 /* ServerActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F2EFEF24076B0900198159 /* ServerActions.swift */; }; E4F2EFF224076B5E00198159 /* ServerReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F2EFF124076B5E00198159 /* ServerReducer.swift */; }; + E4F365D224942CC7006A8C4A /* NowPlayingTabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F365D024942C6A006A8C4A /* NowPlayingTabBarController.swift */; }; + E4F365D4249432C0006A8C4A /* NowPlayingTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F365D3249432C0006A8C4A /* NowPlayingTabBar.swift */; }; + E4F365D6249C4CDC006A8C4A /* UIImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F365D5249C4CDC006A8C4A /* UIImage.swift */; }; E4F6B460221E119B00ACF42A /* QueueDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F6B45F221E119B00ACF42A /* QueueDataSource.swift */; }; E4F6B463221E125900ACF42A /* QueueItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F6B462221E125900ACF42A /* QueueItem.swift */; }; E4F6B467221E233200ACF42A /* AlbumDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F6B466221E233200ACF42A /* AlbumDataSource.swift */; }; @@ -394,6 +399,8 @@ /* Begin PBXFileReference section */ 38BAC36A249CB1A6004BAEA4 /* AlbumDetailSongTitleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlbumDetailSongTitleView.swift; sourceTree = ""; }; + E403E63C246F4C3900200F58 /* NowPlayingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NowPlayingViewController.swift; sourceTree = ""; }; + E403E63D246F4C3900200F58 /* NowPlayingViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NowPlayingViewController.xib; sourceTree = ""; }; E40786182110CE6E006887B1 /* Persephone.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Persephone.app; sourceTree = BUILT_PRODUCTS_DIR; }; E407861B2110CE6E006887B1 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; E407861F2110CE70006887B1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -683,6 +690,9 @@ E4F2EFED24076A2700198159 /* ServerState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerState.swift; sourceTree = ""; }; E4F2EFEF24076B0900198159 /* ServerActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerActions.swift; sourceTree = ""; }; E4F2EFF124076B5E00198159 /* ServerReducer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerReducer.swift; sourceTree = ""; }; + E4F365D024942C6A006A8C4A /* NowPlayingTabBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NowPlayingTabBarController.swift; sourceTree = ""; }; + E4F365D3249432C0006A8C4A /* NowPlayingTabBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NowPlayingTabBar.swift; sourceTree = ""; }; + E4F365D5249C4CDC006A8C4A /* UIImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIImage.swift; sourceTree = ""; }; E4F6B45F221E119B00ACF42A /* QueueDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueueDataSource.swift; sourceTree = ""; }; E4F6B462221E125900ACF42A /* QueueItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueueItem.swift; sourceTree = ""; }; E4F6B466221E233200ACF42A /* AlbumDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlbumDataSource.swift; sourceTree = ""; }; @@ -914,6 +924,7 @@ E41222062431425400473C1D /* Components */ = { isa = PBXGroup; children = ( + E4D4FAE6246F4B1B00CD02AF /* Now Playing */, E41222252431538700473C1D /* Shared */, E41222072431425400473C1D /* Browser */, ); @@ -954,6 +965,7 @@ E4928E0A2218D62A001D4BEA /* CGColor.swift */, E41222272431539800473C1D /* CGSize.swift */, E4C51F09243428B60093FB31 /* UIFont.swift */, + E4F365D5249C4CDC006A8C4A /* UIImage.swift */, ); path = Extensions; sourceTree = ""; @@ -1418,6 +1430,17 @@ path = Protocols; sourceTree = ""; }; + E4D4FAE6246F4B1B00CD02AF /* Now Playing */ = { + isa = PBXGroup; + children = ( + E403E63C246F4C3900200F58 /* NowPlayingViewController.swift */, + E403E63D246F4C3900200F58 /* NowPlayingViewController.xib */, + E4F365D024942C6A006A8C4A /* NowPlayingTabBarController.swift */, + E4F365D3249432C0006A8C4A /* NowPlayingTabBar.swift */, + ); + path = "Now Playing"; + sourceTree = ""; + }; E4E13C2C2350D8CB00092A6E /* Layouts */ = { isa = PBXGroup; children = ( @@ -1698,6 +1721,7 @@ E480590F2426D73600362CF3 /* configure.py in Resources */, E48058292426D73500362CF3 /* version.h.in in Resources */, E48059152426D73600362CF3 /* build.sh in Resources */, + E403E63F246F4C3900200F58 /* NowPlayingViewController.xib in Resources */, E48059132426D73600362CF3 /* win32.txt in Resources */, E48059C12426D73600362CF3 /* libmpdclient.vapi in Resources */, E41222162431425400473C1D /* Assets.xcassets in Resources */, @@ -1962,7 +1986,9 @@ E480512C24255BDF00362CF3 /* MPDCommand.swift in Sources */, E48059F52426D73600362CF3 /* search.c in Sources */, E4805A1F2426D73600362CF3 /* idle.c in Sources */, + E4F365D224942CC7006A8C4A /* NowPlayingTabBarController.swift in Sources */, E41222182431425400473C1D /* AlbumItemCell.swift in Sources */, + E4F365D4249432C0006A8C4A /* NowPlayingTabBar.swift in Sources */, E480511724255BAF00362CF3 /* MPDServer.swift in Sources */, E48059C32426D73600362CF3 /* directory.c in Sources */, E480514A24255E7D00362CF3 /* PlayerActions.swift in Sources */, @@ -1982,9 +2008,11 @@ E4B3B3672432DF1B007E25D2 /* AlbumSongListViewController.swift in Sources */, E480514524255E7700362CF3 /* PreferencesReducer.swift in Sources */, E41222292431555100473C1D /* CGColor.swift in Sources */, + E4F365D6249C4CDC006A8C4A /* UIImage.swift in Sources */, E480511F24255BDB00362CF3 /* MPDClient+Album.swift in Sources */, E4805A0B2426D73600362CF3 /* sync.c in Sources */, E4805A052426D73600362CF3 /* connection.c in Sources */, + E403E63E246F4C3900200F58 /* NowPlayingViewController.swift in Sources */, E480512324255BDB00362CF3 /* MPDClient+Database.swift in Sources */, E41222302432B0A300473C1D /* AlbumTracksDataSource.swift in Sources */, E48059ED2426D73600362CF3 /* stats.c in Sources */, diff --git a/iOS/Assets.xcassets/playButtonLarge.imageset/playButtonLarge.pdf b/Resources/export/nextTrackButtonLarge.pdf similarity index 79% rename from iOS/Assets.xcassets/playButtonLarge.imageset/playButtonLarge.pdf rename to Resources/export/nextTrackButtonLarge.pdf index a04b172..364255c 100644 Binary files a/iOS/Assets.xcassets/playButtonLarge.imageset/playButtonLarge.pdf and b/Resources/export/nextTrackButtonLarge.pdf differ diff --git a/Resources/export/nextTrackButtonLarge.png b/Resources/export/nextTrackButtonLarge.png new file mode 100644 index 0000000..3e05e82 Binary files /dev/null and b/Resources/export/nextTrackButtonLarge.png differ diff --git a/Resources/export/nextTrackButtonLarge@2x.png b/Resources/export/nextTrackButtonLarge@2x.png new file mode 100644 index 0000000..e3e7b10 Binary files /dev/null and b/Resources/export/nextTrackButtonLarge@2x.png differ diff --git a/Resources/export/nextTrackButtonLarge@3x.png b/Resources/export/nextTrackButtonLarge@3x.png new file mode 100644 index 0000000..89a7813 Binary files /dev/null and b/Resources/export/nextTrackButtonLarge@3x.png differ diff --git a/Resources/export/nextTrackButtonLargeiOS.pdf b/Resources/export/nextTrackButtonLargeiOS.pdf new file mode 100644 index 0000000..30c8349 Binary files /dev/null and b/Resources/export/nextTrackButtonLargeiOS.pdf differ diff --git a/Resources/export/nextTrackButtonLargeiOS.png b/Resources/export/nextTrackButtonLargeiOS.png new file mode 100644 index 0000000..895f2d4 Binary files /dev/null and b/Resources/export/nextTrackButtonLargeiOS.png differ diff --git a/Resources/export/nextTrackButtonLargeiOS@2x.png b/Resources/export/nextTrackButtonLargeiOS@2x.png new file mode 100644 index 0000000..fa49346 Binary files /dev/null and b/Resources/export/nextTrackButtonLargeiOS@2x.png differ diff --git a/Resources/export/nextTrackButtonLargeiOS@3x.png b/Resources/export/nextTrackButtonLargeiOS@3x.png new file mode 100644 index 0000000..49dd944 Binary files /dev/null and b/Resources/export/nextTrackButtonLargeiOS@3x.png differ diff --git a/Resources/export/pauseButtonLargeiOS.pdf b/Resources/export/pauseButtonLargeiOS.pdf new file mode 100644 index 0000000..0680892 Binary files /dev/null and b/Resources/export/pauseButtonLargeiOS.pdf differ diff --git a/Resources/export/pauseButtonLargeiOS.png b/Resources/export/pauseButtonLargeiOS.png new file mode 100644 index 0000000..c56a775 Binary files /dev/null and b/Resources/export/pauseButtonLargeiOS.png differ diff --git a/Resources/export/pauseButtonLargeiOS@2x.png b/Resources/export/pauseButtonLargeiOS@2x.png new file mode 100644 index 0000000..792814e Binary files /dev/null and b/Resources/export/pauseButtonLargeiOS@2x.png differ diff --git a/Resources/export/pauseButtonLargeiOS@3x.png b/Resources/export/pauseButtonLargeiOS@3x.png new file mode 100644 index 0000000..605efca Binary files /dev/null and b/Resources/export/pauseButtonLargeiOS@3x.png differ diff --git a/Resources/export/playButtonLarge.pdf b/Resources/export/playButtonLarge.pdf index a04b172..b354ccb 100644 Binary files a/Resources/export/playButtonLarge.pdf and b/Resources/export/playButtonLarge.pdf differ diff --git a/Resources/export/playButtonLarge.png b/Resources/export/playButtonLarge.png index a489b7b..9e29316 100644 Binary files a/Resources/export/playButtonLarge.png and b/Resources/export/playButtonLarge.png differ diff --git a/Resources/export/playButtonLarge@2x.png b/Resources/export/playButtonLarge@2x.png index 109a9ca..4604852 100644 Binary files a/Resources/export/playButtonLarge@2x.png and b/Resources/export/playButtonLarge@2x.png differ diff --git a/Resources/export/playButtonLarge@3x.png b/Resources/export/playButtonLarge@3x.png new file mode 100644 index 0000000..32fe1e6 Binary files /dev/null and b/Resources/export/playButtonLarge@3x.png differ diff --git a/Resources/export/playButtonLargeiOS.pdf b/Resources/export/playButtonLargeiOS.pdf new file mode 100644 index 0000000..faad7a1 Binary files /dev/null and b/Resources/export/playButtonLargeiOS.pdf differ diff --git a/Resources/export/playButtonLargeiOS.png b/Resources/export/playButtonLargeiOS.png new file mode 100644 index 0000000..8eaa316 Binary files /dev/null and b/Resources/export/playButtonLargeiOS.png differ diff --git a/Resources/export/playButtonLargeiOS@2x.png b/Resources/export/playButtonLargeiOS@2x.png new file mode 100644 index 0000000..a00fe2d Binary files /dev/null and b/Resources/export/playButtonLargeiOS@2x.png differ diff --git a/Resources/export/playButtonLargeiOS@3x.png b/Resources/export/playButtonLargeiOS@3x.png new file mode 100644 index 0000000..41ab03f Binary files /dev/null and b/Resources/export/playButtonLargeiOS@3x.png differ diff --git a/Resources/icons.sketch b/Resources/icons.sketch index eb180ac..2a5d316 100644 Binary files a/Resources/icons.sketch and b/Resources/icons.sketch differ diff --git a/iOS/Assets.xcassets/nextTrackButtonLarge.imageset/Contents.json b/iOS/Assets.xcassets/nextTrackButtonLarge.imageset/Contents.json new file mode 100644 index 0000000..6f87921 --- /dev/null +++ b/iOS/Assets.xcassets/nextTrackButtonLarge.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "nextTrackButtonLargeiOS.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/iOS/Assets.xcassets/nextTrackButtonLarge.imageset/nextTrackButtonLargeiOS.pdf b/iOS/Assets.xcassets/nextTrackButtonLarge.imageset/nextTrackButtonLargeiOS.pdf new file mode 100644 index 0000000..d560bd4 Binary files /dev/null and b/iOS/Assets.xcassets/nextTrackButtonLarge.imageset/nextTrackButtonLargeiOS.pdf differ diff --git a/iOS/Assets.xcassets/pauseButtonLarge.imageset/Contents.json b/iOS/Assets.xcassets/pauseButtonLarge.imageset/Contents.json new file mode 100644 index 0000000..56a5a2c --- /dev/null +++ b/iOS/Assets.xcassets/pauseButtonLarge.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "pauseButtonLargeiOS.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/iOS/Assets.xcassets/pauseButtonLarge.imageset/pauseButtonLargeiOS.pdf b/iOS/Assets.xcassets/pauseButtonLarge.imageset/pauseButtonLargeiOS.pdf new file mode 100644 index 0000000..0680892 Binary files /dev/null and b/iOS/Assets.xcassets/pauseButtonLarge.imageset/pauseButtonLargeiOS.pdf differ diff --git a/iOS/Assets.xcassets/playButtonLarge.imageset/Contents.json b/iOS/Assets.xcassets/playButtonLarge.imageset/Contents.json index f5d8b34..2276e67 100644 --- a/iOS/Assets.xcassets/playButtonLarge.imageset/Contents.json +++ b/iOS/Assets.xcassets/playButtonLarge.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "playButtonLarge.pdf", + "filename" : "playButtonLargeiOS.pdf", "idiom" : "universal" } ], diff --git a/iOS/Assets.xcassets/playButtonLarge.imageset/playButtonLargeiOS.pdf b/iOS/Assets.xcassets/playButtonLarge.imageset/playButtonLargeiOS.pdf new file mode 100644 index 0000000..84497df Binary files /dev/null and b/iOS/Assets.xcassets/playButtonLarge.imageset/playButtonLargeiOS.pdf differ diff --git a/iOS/Base.lproj/Main.storyboard b/iOS/Base.lproj/Main.storyboard index a36e16a..3a12470 100644 --- a/iOS/Base.lproj/Main.storyboard +++ b/iOS/Base.lproj/Main.storyboard @@ -1,8 +1,9 @@ - + - + + @@ -78,7 +79,7 @@ - + @@ -93,8 +94,11 @@ - - + - + - + + - + + + + + + + + + + + + + + + + + @@ -302,11 +323,12 @@ - + + diff --git a/iOS/Components/Browser/Album Browser/AlbumItemCell.swift b/iOS/Components/Browser/Album Browser/AlbumItemCell.swift index 4dd30dd..44a4f1b 100644 --- a/iOS/Components/Browser/Album Browser/AlbumItemCell.swift +++ b/iOS/Components/Browser/Album Browser/AlbumItemCell.swift @@ -15,7 +15,7 @@ class AlbumItemCell: UICollectionViewCell { override func didMoveToSuperview() { albumCoverView.layer.backgroundColor = UIColor.black.cgColor albumCoverView.layer.cornerRadius = 4 - albumCoverView.layer.borderWidth = 0.5 + albumCoverView.layer.borderWidth = 1 / traitCollection.displayScale albumCoverView.layer.masksToBounds = true setAppearance() } diff --git a/iOS/Components/Browser/Album Detail/AlbumSongListViewController.swift b/iOS/Components/Browser/Album Detail/AlbumSongListViewController.swift index c00396d..26c9f3d 100644 --- a/iOS/Components/Browser/Album Detail/AlbumSongListViewController.swift +++ b/iOS/Components/Browser/Album Detail/AlbumSongListViewController.swift @@ -24,7 +24,7 @@ class AlbumSongListViewController: UITableViewController { albumCoverView.layer.backgroundColor = UIColor.black.cgColor albumCoverView.layer.cornerRadius = 4 - albumCoverView.layer.borderWidth = 0.5 + albumCoverView.layer.borderWidth = 1 / traitCollection.displayScale albumCoverView.layer.masksToBounds = true playAlbumButton.layer.cornerRadius = 8 @@ -116,6 +116,8 @@ class AlbumSongListViewController: UITableViewController { } override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + if traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) { setAppearance() } diff --git a/iOS/Components/Now Playing/NowPlayingTabBar.swift b/iOS/Components/Now Playing/NowPlayingTabBar.swift new file mode 100644 index 0000000..7a40209 --- /dev/null +++ b/iOS/Components/Now Playing/NowPlayingTabBar.swift @@ -0,0 +1,47 @@ +// +// NowPlayingTabBar.swift +// Persephone-iOS +// +// Created by Dan Barber on 2020-6-12. +// Copyright © 2020 Dan Barber. All rights reserved. +// + +import UIKit + +class NowPlayingControlBackground: UIControl { +// override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool { +// +// } +// +// override func cancelTracking(with event: UIEvent?) { +// +// } +// +// override func endTracking(_ touch: UITouch?, with event: UIEvent?) { +// +// // if touch is inside your control +// sendActions(for: .touchUpInside) +// } +} + +class NowPlayingTabBar: UITabBar { + static let barHeight: CGFloat = 56 + + override func awakeFromNib() { + super.awakeFromNib() + + let bounds = CGRect(x: 0, y: 0, width: 1, height: 1) + NowPlayingTabBar.appearance().shadowImage = UIGraphicsImageRenderer(bounds: bounds).image { context in + UIColor.systemRed.setFill() + context.fill(bounds) + } + } + + override func layoutSubviews() { + super.layoutSubviews() + + for case let control as UIControl in subviews { + control.frame.origin.y += Self.barHeight + } + } +} diff --git a/iOS/Components/Now Playing/NowPlayingTabBarController.swift b/iOS/Components/Now Playing/NowPlayingTabBarController.swift new file mode 100644 index 0000000..b26baa3 --- /dev/null +++ b/iOS/Components/Now Playing/NowPlayingTabBarController.swift @@ -0,0 +1,40 @@ +// +// NowPlayingTabBarController.swift +// Persephone +// +// Created by Dan Barber on 2020-6-12. +// Copyright © 2020 Dan Barber. All rights reserved. +// + +import UIKit + +class NowPlayingTabBarController: UITabBarController { + private var barHeight: NSLayoutConstraint! + let nowPlayingViewController = NowPlayingViewController() + + override func viewDidLoad() { + super.viewDidLoad() + + addChild(nowPlayingViewController) + let subview = nowPlayingViewController.view! + tabBar.superview?.addSubview(subview) + tabBar.clipsToBounds = false + subview.translatesAutoresizingMaskIntoConstraints = false + barHeight = subview.heightAnchor.constraint(equalToConstant: 0) + NSLayoutConstraint.activate([ + subview.leadingAnchor.constraint(equalTo: view.leadingAnchor), + subview.trailingAnchor.constraint(equalTo: view.trailingAnchor), + subview.topAnchor.constraint(equalTo: tabBar.topAnchor), + barHeight, + ]) + nowPlayingViewController.didMove(toParent: self) + + additionalSafeAreaInsets.bottom = NowPlayingTabBar.barHeight + } + + override func preferredContentSizeDidChange(forChildContentContainer container: UIContentContainer) { + super.preferredContentSizeDidChange(forChildContentContainer: container) + + barHeight.constant = container.preferredContentSize.height + } +} diff --git a/iOS/Components/Now Playing/NowPlayingViewController.swift b/iOS/Components/Now Playing/NowPlayingViewController.swift new file mode 100644 index 0000000..6f2e386 --- /dev/null +++ b/iOS/Components/Now Playing/NowPlayingViewController.swift @@ -0,0 +1,133 @@ +// +// NowPlayingViewController.swift +// Persephone-iOS +// +// Created by Dan Barber on 2020-5-15. +// Copyright © 2020 Dan Barber. All rights reserved. +// + +import UIKit +import ReSwift +import Kingfisher + +class NowPlayingViewController: UIViewController { + @IBOutlet var separatorHeight: NSLayoutConstraint! + @IBOutlet var playPauseButton: UIButton! + @IBOutlet var nextButton: UIButton! + @IBOutlet var songTitle: UILabel! + @IBOutlet var albumCoverView: UIImageView! + + override func viewDidLoad() { + super.viewDidLoad() + + separatorHeight.constant = 1 / traitCollection.displayScale + + App.store.subscribe(self) { + $0.select { $0.playerState } + } + + NotificationCenter.default.addObserver(self, selector: #selector(didConnect), name: .didConnect, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(willDisconnect), name: .willDisconnect, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(didReloadAlbumArt), name: .didReloadAlbumArt, object: nil) + + albumCoverView.layer.backgroundColor = UIColor.black.cgColor + albumCoverView.layer.cornerRadius = 4 + albumCoverView.layer.borderWidth = 1 / traitCollection.displayScale + albumCoverView.layer.masksToBounds = true + + setAppearance() + } + + override func didMove(toParent parent: UIViewController?) { + super.didMove(toParent: parent) + + preferredContentSize.height = NowPlayingTabBar.barHeight + } + + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + + separatorHeight.constant = 1 / traitCollection.displayScale + + if traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) { + setAppearance() + } + } + + func setAppearance() { + let darkMode = traitCollection.userInterfaceStyle == .dark + + albumCoverView.layer.borderColor = darkMode ? CGColor.albumBorderColorDark : CGColor.albumBorderColorLight + } + + @objc func didConnect() { + App.mpdClient.fetchQueue() + } + + @objc func willDisconnect() { + DispatchQueue.main.async { + App.store.dispatch(UpdateQueuePosAction(queuePos: -1)) + App.store.dispatch(UpdateQueueAction(queue: [])) + } + } + + @objc func didReloadAlbumArt() { + // NO-OP + } + + func setTransportControlState(_ state: PlayerState) { + guard let state = state.state else { return } + + playPauseButton.isEnabled = state.isOneOf([.playing, .paused, .stopped]) + nextButton.isEnabled = state.isOneOf([.playing, .paused]) + + if state.isOneOf([.paused, .stopped, .unknown]) { + playPauseButton.setImage(.playIconLarge, for: .normal) + } else { + playPauseButton.setImage(.pauseIconLarge, for: .normal) + } + } + + func setSong(_ song: Song?) { + guard let song = song else { + self.songTitle.text = "Not Playing" + self.albumCoverView.image = .defaultCoverArt + return + } + + songTitle.text = song.title + + let provider = MPDAlbumArtImageDataProvider( + songUri: song.mpdSong.uriString, + cacheKey: song.album.hash + ) + + albumCoverView.kf.setImage( + with: .provider(provider), + placeholder: UIImage.defaultCoverArt, + options: [ + .processor(DownsamplingImageProcessor(size: .queueSongCoverSize)), + .scaleFactor(traitCollection.displayScale), + ] + ) + } + + @IBAction func playPauseButtonAction(_ sender: Any) { + App.mpdClient.playPause() + } + + @IBAction func nextButtonAction(_ sender: Any) { + App.mpdClient.nextTrack() + } +} + +extension NowPlayingViewController: StoreSubscriber { + typealias StoreSubscriberStateType = PlayerState + + func newState(state: PlayerState) { + DispatchQueue.main.async { + self.setTransportControlState(state) + self.setSong(state.currentSong) + } + } +} diff --git a/iOS/Components/Now Playing/NowPlayingViewController.xib b/iOS/Components/Now Playing/NowPlayingViewController.xib new file mode 100644 index 0000000..57666fb --- /dev/null +++ b/iOS/Components/Now Playing/NowPlayingViewController.xib @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iOS/Components/Shared/Extensions/UIImage.swift b/iOS/Components/Shared/Extensions/UIImage.swift new file mode 100644 index 0000000..ea3b955 --- /dev/null +++ b/iOS/Components/Shared/Extensions/UIImage.swift @@ -0,0 +1,15 @@ +// +// UIImage.swift +// Persephone-iOS +// +// Created by Dan Barber on 2020-6-18. +// Copyright © 2020 Dan Barber. All rights reserved. +// + +import UIKit + +extension UIImage { + static let defaultCoverArt = UIImage(named: "defaultCoverArt") + static let playIconLarge = UIImage(named: "playButtonLarge") + static let pauseIconLarge = UIImage(named: "pauseButtonLarge") +}