import SwiftUI | |
import PlaygroundSupport | |
struct showArt: View { | |
@Binding var isPlaying: Bool | |
var body: some View { | |
VStack { | |
VStack { | |
RoundedRectangle(cornerRadius: 16) | |
.shadow(color: Color(UIColor.black.withAlphaComponent( isPlaying ? 0.3 : 0.1)), radius: 20, x: 0, y: 10) | |
.frame(width: isPlaying ? 325 : 300, height: isPlaying ? 325 : 300) | |
.animation(.default) | |
} | |
.foregroundColor(Color.yellow) | |
} | |
.frame(width: 325, height: 325) | |
} | |
} | |
struct PlayerTimeline: View { | |
var body: some View { | |
VStack { | |
ZStack { | |
Rectangle() | |
.frame(height: 3) | |
.cornerRadius(3) | |
.foregroundColor(Color(UIColor.tertiaryLabel)) | |
Circle() | |
.frame(height: 8) | |
.foregroundColor(Color(UIColor.gray)) | |
} | |
HStack { | |
Text("2:01") | |
.font(.footnote) | |
.foregroundColor(Color(UIColor.tertiaryLabel)) | |
Spacer() | |
Text("4:00") | |
.font(.footnote) | |
.foregroundColor(Color(UIColor.tertiaryLabel)) | |
} | |
} | |
} | |
} | |
struct PodcastInfo: View { | |
var body: some View { | |
HStack { | |
Group { | |
VStack (alignment: .center, spacing: 4) { | |
Text("Optimism in 2020") | |
.font(.system(size: 26)) | |
.fontWeight(.medium) | |
.multilineTextAlignment(.center) | |
Text("Today, Explained") | |
.font(.system(size: 24)) | |
.foregroundColor(Color(UIColor.systemPurple)) | |
.multilineTextAlignment(.center) | |
} | |
} | |
} | |
} | |
} | |
struct controls: View { | |
@Binding var isPlaying: Bool | |
@State var pressed = false | |
var body: some View { | |
VStack { | |
HStack { | |
Image(systemName: "gobackward.30") | |
.font(.system(size: 32)) | |
Spacer() | |
Image(systemName: self.isPlaying ? "pause.fill" : "play.fill") | |
.onTapGesture { | |
self.isPlaying.toggle() | |
} | |
.font(.system(size: 48)) | |
.scaleEffect(self.pressed ? 0.9 : 1.0) | |
.onLongPressGesture(minimumDuration: .infinity, maximumDistance: .infinity, pressing: { pressing in | |
withAnimation(.easeInOut(duration: 0.1)) { | |
self.pressed = pressing | |
} | |
}, perform: { }) | |
Spacer() | |
Image(systemName: "goforward.45") | |
.font(.system(size: 32)) | |
} | |
.frame(width: 250) | |
} | |
} | |
} | |
struct volume: View { | |
@State var volume = 25.0 | |
var body: some View { | |
VStack { | |
HStack(spacing: 12) { | |
Image(systemName: "volume.fill") | |
.font(.system(size: 16)) | |
.foregroundColor(Color(UIColor.tertiaryLabel)) | |
Slider(value: $volume, in: 0...100) | |
.accentColor(Color(UIColor.gray)) | |
Image(systemName: "volume.3.fill") | |
.font(.system(size: 16)) | |
.foregroundColor(Color(UIColor.tertiaryLabel)) | |
} | |
} | |
} | |
} | |
struct IconRow: View { | |
@State var airplayActive = false | |
@State var pressed = false | |
let playBackSpeeds = ["1x", "1.5x", "2x"] | |
@State var count = 0 | |
var body: some View { | |
VStack (spacing: 16) { | |
HStack { | |
VStack { | |
Text("\(playBackSpeeds[self.count])") | |
.onTapGesture { | |
self.count += 1 | |
if self.count >= self.playBackSpeeds.count { | |
self.count = 0 | |
} | |
} | |
.font(.system(size: 24)) | |
.foregroundColor(Color(UIColor.systemPurple)) | |
} | |
.frame(width: 56) | |
Spacer() | |
Image(systemName: "airplayaudio") | |
.onTapGesture { | |
self.airplayActive.toggle() | |
} | |
.scaleEffect(self.pressed ? 0.9 : 1.0) | |
.onLongPressGesture(minimumDuration: .infinity, maximumDistance: .infinity, pressing: { pressing in | |
withAnimation(.easeInOut(duration: 0.1)) { | |
self.pressed = pressing | |
} | |
}, perform: { }) | |
.font(.system(size: 24)) | |
.foregroundColor(Color(self.airplayActive ? UIColor.systemPurple : UIColor.label)) | |
.frame(width: 56) | |
Spacer() | |
Image(systemName: "ellipsis") | |
.font(.system(size: 24)) | |
.foregroundColor(Color(UIColor.systemPurple)) | |
.frame(width: 56) | |
} | |
HStack { | |
if airplayActive == true { | |
Text("iPhone → Desk Homepod") | |
.font(.caption) | |
.fontWeight(.semibold) | |
.foregroundColor(Color(UIColor.systemPurple)) | |
} else { | |
Text(" ") | |
.font(.caption) | |
.fontWeight(.semibold) | |
} | |
} | |
} | |
.frame(width: 250) | |
} | |
} | |
struct Screen: View { | |
@State var isPlaying = false | |
var body: some View { | |
ZStack { | |
Color(UIColor.secondarySystemBackground) | |
VStack (spacing: 24) { | |
Spacer() | |
showArt(isPlaying: $isPlaying) | |
Spacer() | |
Group { | |
PlayerTimeline() | |
PodcastInfo() | |
Spacer() | |
controls(isPlaying: $isPlaying) | |
Spacer() | |
volume() | |
} | |
Spacer() | |
IconRow() | |
} | |
.frame(width: 350, height: 812) | |
.padding(32) | |
.background(Color.white) | |
} | |
} | |
} | |
PlaygroundPage.current.setLiveView(Screen()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment