Fix login bug, remove empty homescreen, add landscape MovieItemView
This commit is contained in:
parent
ee0f46576e
commit
63f7264902
|
@ -11,6 +11,7 @@ import SwiftyRequest
|
|||
import SwiftyJSON
|
||||
import CoreData
|
||||
import KeychainSwift
|
||||
import Introspect
|
||||
|
||||
struct ConnectToServerView: View {
|
||||
@Environment(\.managedObjectContext) private var viewContext
|
||||
|
@ -193,5 +194,8 @@ struct ConnectToServerView: View {
|
|||
}
|
||||
.onAppear(perform: start)
|
||||
.transition(.move(edge:.bottom))
|
||||
.introspectTabBarController { (UITabBarController) in
|
||||
UITabBarController.tabBar.isHidden = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import SwiftUI
|
|||
import KeychainSwift
|
||||
import SwiftyRequest
|
||||
import SwiftyJSON
|
||||
import Introspect
|
||||
|
||||
class GlobalData: ObservableObject {
|
||||
@Published var user: SignedInUser?
|
||||
|
@ -134,9 +135,6 @@ class PreferenceUIHostingController: UIHostingController<AnyView> {
|
|||
if(_orientations == .landscapeRight) {
|
||||
let value = UIInterfaceOrientation.landscapeRight.rawValue;
|
||||
UIDevice.current.setValue(value, forKey: "orientation")
|
||||
} else {
|
||||
let value = UIInterfaceOrientation.portrait.rawValue;
|
||||
UIDevice.current.setValue(value, forKey: "orientation")
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -186,6 +184,7 @@ struct ContentView: View {
|
|||
@State private var library_names: [String: String] = [:];
|
||||
@State private var librariesShowRecentlyAdded: [String] = [];
|
||||
@State private var libraryPrefillID: String = "";
|
||||
@State private var showSettingsPopover: Bool = false;
|
||||
|
||||
@Environment(\.verticalSizeClass) var verticalSizeClass: UserInterfaceSizeClass?
|
||||
@Environment(\.horizontalSizeClass) var horizontalSizeClass: UserInterfaceSizeClass?
|
||||
|
@ -309,12 +308,12 @@ struct ContentView: View {
|
|||
.toolbar {
|
||||
ToolbarItemGroup(placement: .navigationBarTrailing) {
|
||||
Button {
|
||||
print("Settings tapped!")
|
||||
showSettingsPopover = true;
|
||||
} label: {
|
||||
Image(systemName: "gear")
|
||||
}
|
||||
}
|
||||
}
|
||||
}.popover( isPresented: self.$showSettingsPopover, arrowEdge: .bottom) { SettingsView(close: $showSettingsPopover).environmentObject(self.globalData) }
|
||||
}
|
||||
.tabItem({
|
||||
Text("Home")
|
||||
|
@ -337,14 +336,15 @@ struct ContentView: View {
|
|||
.navigationViewStyle(StackNavigationViewStyle())
|
||||
.alert(isPresented: $isNetworkErrored) {
|
||||
Alert(title: Text("Network Error"), message: Text("Couldn't connect to Jellyfin"), dismissButton: .default(Text("Ok")))
|
||||
}.introspectTabBarController { (UITabBarController) in
|
||||
UITabBarController.tabBar.isHidden = false
|
||||
}
|
||||
} else {
|
||||
Text("Signing in...")
|
||||
.onAppear(perform: {
|
||||
DispatchQueue.global(qos: .userInitiated).async { [self] in
|
||||
print("Signing in")
|
||||
sleep(3)
|
||||
jsi.did = false
|
||||
usleep(500000);
|
||||
self.jsi.did = false;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -75,78 +75,84 @@ struct ContinueWatchingView: View {
|
|||
}
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
HStack() {
|
||||
if(isLoading == false) {
|
||||
Spacer().frame(width:16)
|
||||
ForEach(resumeItems, id: \.Id) { item in
|
||||
NavigationLink(destination: ItemView(item: item)) {
|
||||
VStack(alignment: .leading) {
|
||||
Spacer().frame(height: 10)
|
||||
if(item.Type == "Episode") {
|
||||
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?fillWidth=560&fillHeight=315&quality=90&tag=\(item.Image)")!)
|
||||
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
|
||||
.placeholder {
|
||||
Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 32, height: 32))!)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.cornerRadius(10)
|
||||
}
|
||||
.frame(width: 320, height: 180)
|
||||
.cornerRadius(10)
|
||||
.overlay(
|
||||
ZStack {
|
||||
Text("S\(String(item.ParentIndexNumber ?? 0)):E\(String(item.IndexNumber ?? 0)) - \(item.Name)")
|
||||
.font(.caption)
|
||||
.padding(6)
|
||||
.foregroundColor(.white)
|
||||
}.background(Color.black)
|
||||
.opacity(0.8)
|
||||
.cornerRadius(10.0)
|
||||
.padding(6), alignment: .topTrailing
|
||||
)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 10, style: .circular)
|
||||
.fill(Color(red: 172/255, green: 92/255, blue: 195/255).opacity(0.4))
|
||||
.frame(width: CGFloat((item.ItemProgress/100)*320), height: 180)
|
||||
.padding(0), alignment: .bottomLeading
|
||||
)
|
||||
.shadow(radius: 5)
|
||||
} else {
|
||||
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?fillWidth=560&fillHeight=315&quality=90&tag=\(item.Image)")!)
|
||||
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
|
||||
.placeholder {
|
||||
Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 32, height: 32))!)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.cornerRadius(10)
|
||||
}
|
||||
.frame(width: 320, height: 180)
|
||||
.cornerRadius(10)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 10, style: .circular)
|
||||
.fill(Color(red: 172/255, green: 92/255, blue: 195/255).opacity(0.4))
|
||||
.frame(width: CGFloat((item.ItemProgress/100)*320), height: 180)
|
||||
.padding(0), alignment: .bottomLeading
|
||||
)
|
||||
.shadow(radius: 5)
|
||||
}
|
||||
Text("\(item.Type == "Episode" ? item.SeriesName ?? "" : item.Name)")
|
||||
.font(.callout)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.primary)
|
||||
Spacer().frame(height: 5)
|
||||
}.padding(.trailing, 5)
|
||||
if(resumeItems.count != 0) {
|
||||
VStack(alignment: .leading) {
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
HStack() {
|
||||
if(isLoading == false) {
|
||||
Spacer().frame(width:16)
|
||||
ForEach(resumeItems, id: \.Id) { item in
|
||||
NavigationLink(destination: ItemView(item: item)) {
|
||||
VStack(alignment: .leading) {
|
||||
Spacer().frame(height: 10)
|
||||
if(item.Type == "Episode") {
|
||||
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?fillWidth=560&fillHeight=315&quality=90&tag=\(item.Image)")!)
|
||||
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
|
||||
.placeholder {
|
||||
Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 32, height: 32))!)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.cornerRadius(10)
|
||||
}
|
||||
.frame(width: 320, height: 180)
|
||||
.cornerRadius(10)
|
||||
.overlay(
|
||||
ZStack {
|
||||
Text("S\(String(item.ParentIndexNumber ?? 0)):E\(String(item.IndexNumber ?? 0)) - \(item.Name)")
|
||||
.font(.caption)
|
||||
.padding(6)
|
||||
.foregroundColor(.white)
|
||||
}.background(Color.black)
|
||||
.opacity(0.8)
|
||||
.cornerRadius(10.0)
|
||||
.padding(6), alignment: .topTrailing
|
||||
)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 10, style: .circular)
|
||||
.fill(Color(red: 172/255, green: 92/255, blue: 195/255).opacity(0.4))
|
||||
.frame(width: CGFloat((item.ItemProgress/100)*320), height: 180)
|
||||
.padding(0), alignment: .bottomLeading
|
||||
)
|
||||
.shadow(radius: 5)
|
||||
} else {
|
||||
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?fillWidth=560&fillHeight=315&quality=90&tag=\(item.Image)")!)
|
||||
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
|
||||
.placeholder {
|
||||
Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 32, height: 32))!)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.cornerRadius(10)
|
||||
}
|
||||
.frame(width: 320, height: 180)
|
||||
.cornerRadius(10)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 10, style: .circular)
|
||||
.fill(Color(red: 172/255, green: 92/255, blue: 195/255).opacity(0.4))
|
||||
.frame(width: CGFloat((item.ItemProgress/100)*320), height: 180)
|
||||
.padding(0), alignment: .bottomLeading
|
||||
)
|
||||
.shadow(radius: 5)
|
||||
}
|
||||
Text("\(item.Type == "Episode" ? item.SeriesName ?? "" : item.Name)")
|
||||
.font(.callout)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.primary)
|
||||
Spacer().frame(height: 5)
|
||||
}.padding(.trailing, 5)
|
||||
}
|
||||
}
|
||||
Spacer().frame(width:14)
|
||||
}
|
||||
Spacer().frame(width:14)
|
||||
}
|
||||
}
|
||||
.frame(height: 200)
|
||||
.padding(.bottom, 10)
|
||||
}
|
||||
.frame(height: 200)
|
||||
.padding(.bottom, 10)
|
||||
}.onAppear(perform: onAppear)
|
||||
} else {
|
||||
VStack() {
|
||||
EmptyView()
|
||||
}.onAppear(perform: onAppear)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -240,6 +240,14 @@ struct MovieItemView: View {
|
|||
}
|
||||
}
|
||||
|
||||
@Environment(\.verticalSizeClass) var verticalSizeClass: UserInterfaceSizeClass?
|
||||
@Environment(\.horizontalSizeClass) var horizontalSizeClass: UserInterfaceSizeClass?
|
||||
|
||||
var isPortrait: Bool {
|
||||
let result = verticalSizeClass == .regular && horizontalSizeClass == .compact
|
||||
return result
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
if(playing) {
|
||||
PlayerDemo(item: fullItem, playing: $playing).onAppear(perform: lockOrientations)
|
||||
|
@ -247,191 +255,375 @@ struct MovieItemView: View {
|
|||
LoadingView(isShowing: $isLoading) {
|
||||
VStack(alignment:.leading) {
|
||||
if(!isLoading) {
|
||||
GeometryReader { geometry in
|
||||
VStack() {
|
||||
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.Id)/Images/Backdrop?maxWidth=3840&quality=90&tag=\(fullItem.Backdrop)")!)
|
||||
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
|
||||
.placeholder {
|
||||
Image(uiImage: UIImage(blurHash: (fullItem.BackdropBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : fullItem.BackdropBlurHash), size: CGSize(width: 32, height: 32))!)
|
||||
.resizable()
|
||||
.frame(width: geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing, height: (geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing) * 0.5625)
|
||||
}
|
||||
if(isPortrait) {
|
||||
GeometryReader { geometry in
|
||||
VStack() {
|
||||
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.Id)/Images/Backdrop?maxWidth=3840&quality=90&tag=\(fullItem.Backdrop)")!)
|
||||
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
|
||||
.placeholder {
|
||||
Image(uiImage: UIImage(blurHash: (fullItem.BackdropBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : fullItem.BackdropBlurHash), size: CGSize(width: 32, height: 32))!)
|
||||
.resizable()
|
||||
.frame(width: geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing, height: (geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing) * 0.5625)
|
||||
}
|
||||
|
||||
.opacity(0.4)
|
||||
.frame(width: geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing, height: (geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing) * 0.5625)
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.shadow(radius: 5)
|
||||
.overlay(
|
||||
.opacity(0.4)
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing, height: (geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing) * 0.5625)
|
||||
.shadow(radius: 5)
|
||||
.overlay(
|
||||
HStack() {
|
||||
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.Id)/Images/Primary?fillWidth=300&fillHeight=450&quality=90&tag=\(fullItem.Poster)")!)
|
||||
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
|
||||
.placeholder {
|
||||
Image(uiImage: UIImage(blurHash: (fullItem.PosterBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : fullItem.PosterBlurHash), size: CGSize(width: 32, height: 32))!)
|
||||
.resizable()
|
||||
.frame(width: 120, height: 180)
|
||||
.cornerRadius(10)
|
||||
}.aspectRatio(contentMode: .fill)
|
||||
.frame(width: 120, height: 180)
|
||||
.cornerRadius(10)
|
||||
VStack(alignment: .leading) {
|
||||
Spacer()
|
||||
Text(fullItem.Name).font(.headline)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.primary)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.offset(y: -4)
|
||||
HStack() {
|
||||
Text(String(fullItem.ProductionYear)).font(.subheadline)
|
||||
.fontWeight(.medium)
|
||||
.foregroundColor(.secondary)
|
||||
.lineLimit(1)
|
||||
Text(fullItem.Runtime).font(.subheadline)
|
||||
.fontWeight(.medium)
|
||||
.foregroundColor(.secondary)
|
||||
.lineLimit(1)
|
||||
if(fullItem.OfficialRating != "") {
|
||||
Text(fullItem.OfficialRating).font(.subheadline)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.secondary)
|
||||
.lineLimit(1)
|
||||
.padding(EdgeInsets(top: 1, leading: 4, bottom: 1, trailing: 4))
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 2)
|
||||
.stroke(Color.secondary, lineWidth: 1)
|
||||
)
|
||||
}
|
||||
if(fullItem.CommunityRating != "") {
|
||||
HStack() {
|
||||
Image(systemName: "star").foregroundColor(.secondary)
|
||||
Text(fullItem.CommunityRating).font(.subheadline)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.secondary)
|
||||
.lineLimit(1)
|
||||
.offset(x: -7, y: 0.7)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}.offset(x: 0, y: -46)
|
||||
}.offset(x: 16, y: 40)
|
||||
, alignment: .bottomLeading)
|
||||
VStack(alignment: .leading) {
|
||||
HStack() {
|
||||
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.Id)/Images/Primary?fillWidth=300&fillHeight=450&quality=90&tag=\(fullItem.Poster)")!)
|
||||
//Play button
|
||||
Button() {
|
||||
playing = true;
|
||||
} label: {
|
||||
HStack() {
|
||||
Text(fullItem.Progress == 0 ? "Play" : "\(progressString) left").foregroundColor(Color.white).font(.callout).fontWeight(.semibold)
|
||||
Image(systemName: "play.fill").foregroundColor(Color.white).font(.system(size: 20))
|
||||
}
|
||||
.frame(width: 120, height: 35)
|
||||
.background(Color(UIColor.systemBlue))
|
||||
.cornerRadius(10)
|
||||
}.buttonStyle(PlainButtonStyle())
|
||||
.frame(width: 120, height: 25)
|
||||
Spacer()
|
||||
HStack() {
|
||||
Button() {
|
||||
favorite.toggle()
|
||||
} label: {
|
||||
if(!favorite) {
|
||||
Image(systemName: "heart").foregroundColor(Color.primary).font(.system(size: 20))
|
||||
} else {
|
||||
Image(systemName: "heart.fill").foregroundColor(Color(UIColor.systemRed)).font(.system(size: 20))
|
||||
}
|
||||
}
|
||||
Button() {
|
||||
watched.toggle()
|
||||
} label: {
|
||||
if(watched) {
|
||||
Image(systemName: "checkmark.rectangle.fill").foregroundColor(Color.primary).font(.system(size: 20))
|
||||
} else {
|
||||
Image(systemName: "xmark.rectangle").foregroundColor(Color.primary).font(.system(size: 20))
|
||||
}
|
||||
}
|
||||
}
|
||||
}.padding(.leading, 16).padding(.trailing,16)
|
||||
ScrollView() {
|
||||
VStack(alignment: .leading) {
|
||||
if(fullItem.Tagline != "") {
|
||||
Text(fullItem.Tagline).font(.body).italic().padding(.top, 7).fixedSize(horizontal: false, vertical: true).padding(.leading, 16).padding(.trailing,16)
|
||||
}
|
||||
Text(fullItem.Overview).font(.footnote).padding(.top, 3).fixedSize(horizontal: false, vertical: true).padding(.bottom, 3).padding(.leading, 16).padding(.trailing,16)
|
||||
if(fullItem.Genres.count != 0) {
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
HStack() {
|
||||
Text("Genres:").font(.callout).fontWeight(.semibold)
|
||||
ForEach(fullItem.Genres, id: \.Id) {genre in
|
||||
NavigationLink(destination: LibraryView(extraParams: "&Genres=\(genre.Name.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "")", title: genre.Name)) {
|
||||
Text(genre.Name).font(.footnote)
|
||||
}
|
||||
}
|
||||
}.padding(.leading, 16).padding(.trailing,16)
|
||||
}
|
||||
}
|
||||
if(fullItem.Cast.count != 0) {
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
VStack() {
|
||||
Spacer().frame(height: 8);
|
||||
HStack() {
|
||||
Spacer().frame(width: 16)
|
||||
ForEach(fullItem.Cast, id: \.Id) { cast in
|
||||
NavigationLink(destination: LibraryView(extraParams: "&PersonIds=\(cast.Id)", title: cast.Name)) {
|
||||
VStack() {
|
||||
WebImage(url: cast.Image)
|
||||
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
|
||||
.placeholder {
|
||||
Image(uiImage: UIImage(blurHash: (cast.ImageBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : cast.ImageBlurHash), size: CGSize(width: 32, height: 32))!)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: 100, height: 100)
|
||||
.cornerRadius(10)
|
||||
}
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: 100, height: 100)
|
||||
.cornerRadius(10).shadow(radius: 6)
|
||||
Text(cast.Name).font(.footnote).fontWeight(.regular).lineLimit(1).frame(width: 100).foregroundColor(Color.primary)
|
||||
if(cast.Role != "") {
|
||||
Text(cast.Role).font(.caption).fontWeight(.medium).lineLimit(1).foregroundColor(Color.secondary).frame(width: 100)
|
||||
}
|
||||
}
|
||||
}
|
||||
Spacer().frame(width: 10)
|
||||
}
|
||||
Spacer().frame(width: 16)
|
||||
}
|
||||
}
|
||||
}.padding(.top, -3)
|
||||
}
|
||||
if(fullItem.Directors.count != 0) {
|
||||
HStack() {
|
||||
Text("Directors:").font(.callout).fontWeight(.semibold)
|
||||
Text(fullItem.Directors.joined(separator: ", ")).font(.footnote).lineLimit(1).foregroundColor(Color.secondary)
|
||||
}.padding(.leading, 16).padding(.trailing,16)
|
||||
}
|
||||
if(fullItem.Writers.count != 0) {
|
||||
HStack() {
|
||||
Text("Writers:").font(.callout).fontWeight(.semibold)
|
||||
Text(fullItem.Writers.joined(separator: ", ")).font(.footnote).lineLimit(1).foregroundColor(Color.secondary)
|
||||
}.padding(.leading, 16).padding(.trailing,16)
|
||||
}
|
||||
if(fullItem.Studios.count != 0) {
|
||||
HStack() {
|
||||
Text("Studios:").font(.callout).fontWeight(.semibold)
|
||||
Text(fullItem.Studios.joined(separator: ", ")).font(.footnote).lineLimit(1).foregroundColor(Color.secondary)
|
||||
}.padding(.leading, 16).padding(.trailing,16)
|
||||
}
|
||||
Spacer().frame(height: 3)
|
||||
}
|
||||
}
|
||||
}.padding(EdgeInsets(top: 24, leading: 0, bottom: 0, trailing: 0))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
GeometryReader { geometry in
|
||||
ZStack() {
|
||||
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.Id)/Images/Backdrop?maxWidth=3840&quality=90&tag=\(fullItem.Backdrop)")!)
|
||||
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
|
||||
.placeholder {
|
||||
Image(uiImage: UIImage(blurHash: (fullItem.BackdropBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : fullItem.BackdropBlurHash), size: CGSize(width: 32, height: 32))!)
|
||||
.resizable()
|
||||
.frame(width: geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing, height: (geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing) * 0.5625)
|
||||
}
|
||||
|
||||
.opacity(0.4)
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing, height: (geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing) * 0.5625)
|
||||
.edgesIgnoringSafeArea(.all)
|
||||
HStack() {
|
||||
VStack() {
|
||||
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.Id)/Images/Primary?maxWidth=300&quality=90&tag=\(fullItem.Poster)")!)
|
||||
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
|
||||
.placeholder {
|
||||
Image(uiImage: UIImage(blurHash: (fullItem.PosterBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : fullItem.PosterBlurHash), size: CGSize(width: 32, height: 32))!)
|
||||
.resizable()
|
||||
.frame(width: 120, height: 180)
|
||||
.cornerRadius(10)
|
||||
}.aspectRatio(contentMode: .fill)
|
||||
}
|
||||
.frame(width: 120, height: 180)
|
||||
.cornerRadius(10)
|
||||
VStack(alignment: .leading) {
|
||||
Spacer()
|
||||
Text(fullItem.Name).font(.headline)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.primary)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.offset(y: -4)
|
||||
.shadow(radius: 5)
|
||||
Spacer().frame(height: 15)
|
||||
Button() {
|
||||
playing = true;
|
||||
} label: {
|
||||
HStack() {
|
||||
Text(String(fullItem.ProductionYear)).font(.subheadline)
|
||||
.fontWeight(.medium)
|
||||
.foregroundColor(.secondary)
|
||||
.lineLimit(1)
|
||||
Text(fullItem.Runtime).font(.subheadline)
|
||||
.fontWeight(.medium)
|
||||
.foregroundColor(.secondary)
|
||||
.lineLimit(1)
|
||||
if(fullItem.OfficialRating != "") {
|
||||
Text(fullItem.OfficialRating).font(.subheadline)
|
||||
Text(fullItem.Progress == 0 ? "Play" : "\(progressString) left").foregroundColor(Color.white).font(.callout).fontWeight(.semibold)
|
||||
Image(systemName: "play.fill").foregroundColor(Color.white).font(.system(size: 20))
|
||||
}
|
||||
.frame(width: 120, height: 35)
|
||||
.background(Color(UIColor.systemBlue))
|
||||
.cornerRadius(10)
|
||||
}.buttonStyle(PlainButtonStyle())
|
||||
.frame(width: 120, height: 25)
|
||||
Spacer()
|
||||
}
|
||||
ScrollView() {
|
||||
VStack(alignment: .leading) {
|
||||
HStack() {
|
||||
VStack(alignment: .leading) {
|
||||
Text(fullItem.Name).font(.headline)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.secondary)
|
||||
.lineLimit(1)
|
||||
.padding(EdgeInsets(top: 1, leading: 4, bottom: 1, trailing: 4))
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 2)
|
||||
.stroke(Color.secondary, lineWidth: 1)
|
||||
)
|
||||
}
|
||||
if(fullItem.CommunityRating != "") {
|
||||
.foregroundColor(.primary)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.offset(x: 11, y: 0)
|
||||
Spacer().frame(height: 1)
|
||||
HStack() {
|
||||
Image(systemName: "star").foregroundColor(.secondary)
|
||||
Text(fullItem.CommunityRating).font(.subheadline)
|
||||
.fontWeight(.semibold)
|
||||
Text(String(fullItem.ProductionYear)).font(.subheadline)
|
||||
.fontWeight(.medium)
|
||||
.foregroundColor(.secondary)
|
||||
.lineLimit(1)
|
||||
.offset(x: -7, y: 0.7)
|
||||
Text(fullItem.Runtime).font(.subheadline)
|
||||
.fontWeight(.medium)
|
||||
.foregroundColor(.secondary)
|
||||
.lineLimit(1)
|
||||
if(fullItem.OfficialRating != "") {
|
||||
Text(fullItem.OfficialRating).font(.subheadline)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.secondary)
|
||||
.lineLimit(1)
|
||||
.padding(EdgeInsets(top: 1, leading: 4, bottom: 1, trailing: 4))
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 2)
|
||||
.stroke(Color.secondary, lineWidth: 1)
|
||||
)
|
||||
}
|
||||
if(fullItem.CommunityRating != "") {
|
||||
HStack() {
|
||||
Image(systemName: "star").foregroundColor(.secondary)
|
||||
Text(fullItem.CommunityRating).font(.subheadline)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.secondary)
|
||||
.lineLimit(1)
|
||||
.offset(x: -7, y: 0.7)
|
||||
}
|
||||
}
|
||||
Spacer()
|
||||
}.frame(maxWidth: .infinity)
|
||||
.offset(x: 11)
|
||||
}.frame(maxWidth: .infinity)
|
||||
Spacer()
|
||||
HStack() {
|
||||
Button() {
|
||||
favorite.toggle()
|
||||
} label: {
|
||||
if(!favorite) {
|
||||
Image(systemName: "heart").foregroundColor(Color.primary).font(.system(size: 20))
|
||||
} else {
|
||||
Image(systemName: "heart.fill").foregroundColor(Color(UIColor.systemRed)).font(.system(size: 20))
|
||||
}
|
||||
}
|
||||
Button() {
|
||||
watched.toggle()
|
||||
} label: {
|
||||
if(watched) {
|
||||
Image(systemName: "checkmark.rectangle.fill").foregroundColor(Color.primary).font(.system(size: 20))
|
||||
} else {
|
||||
Image(systemName: "xmark.rectangle").foregroundColor(Color.primary).font(.system(size: 20))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}.offset(x: 0, y: -46)
|
||||
}.offset(x: 16, y: 40)
|
||||
, alignment: .bottomLeading)
|
||||
VStack(alignment: .leading) {
|
||||
HStack() {
|
||||
//Play button
|
||||
Button() {
|
||||
playing = true;
|
||||
} label: {
|
||||
HStack() {
|
||||
Text(fullItem.Progress == 0 ? "Play" : "\(progressString) left").foregroundColor(Color.white).font(.callout).fontWeight(.semibold)
|
||||
Image(systemName: "play.fill").foregroundColor(Color.white).font(.system(size: 20))
|
||||
}
|
||||
.frame(width: 120, height: 35)
|
||||
.background(Color(UIColor.systemBlue))
|
||||
.cornerRadius(10)
|
||||
}.buttonStyle(PlainButtonStyle())
|
||||
.frame(width: 120, height: 25)
|
||||
Spacer()
|
||||
HStack() {
|
||||
Button() {
|
||||
favorite.toggle()
|
||||
} label: {
|
||||
if(!favorite) {
|
||||
Image(systemName: "heart").foregroundColor(Color.primary).font(.system(size: 20))
|
||||
} else {
|
||||
Image(systemName: "heart.fill").foregroundColor(Color(UIColor.systemRed)).font(.system(size: 20))
|
||||
if(fullItem.Tagline != "") {
|
||||
Text(fullItem.Tagline).font(.body).italic().padding(.top, 3).fixedSize(horizontal: false, vertical: true).padding(.leading, 16).padding(.trailing,16)
|
||||
}
|
||||
}
|
||||
Button() {
|
||||
watched.toggle()
|
||||
} label: {
|
||||
if(watched) {
|
||||
Image(systemName: "checkmark.rectangle.fill").foregroundColor(Color.primary).font(.system(size: 20))
|
||||
} else {
|
||||
Image(systemName: "xmark.rectangle").foregroundColor(Color.primary).font(.system(size: 20))
|
||||
}
|
||||
}
|
||||
}
|
||||
}.padding(.leading, 16).padding(.trailing,16)
|
||||
ScrollView() {
|
||||
VStack(alignment: .leading) {
|
||||
if(fullItem.Tagline != "") {
|
||||
Text(fullItem.Tagline).font(.body).italic().padding(.top, 7).fixedSize(horizontal: false, vertical: true).padding(.leading, 16).padding(.trailing,16)
|
||||
}
|
||||
Text(fullItem.Overview).font(.footnote).padding(.top, 3).fixedSize(horizontal: false, vertical: true).padding(.bottom, 3).padding(.leading, 16).padding(.trailing,16)
|
||||
if(fullItem.Genres.count != 0) {
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
HStack() {
|
||||
Text("Genres:").font(.callout).fontWeight(.semibold)
|
||||
ForEach(fullItem.Genres, id: \.Id) {genre in
|
||||
NavigationLink(destination: LibraryView(extraParams: "&Genres=\(genre.Name.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "")", title: genre.Name)) {
|
||||
Text(genre.Name).font(.footnote)
|
||||
}
|
||||
}
|
||||
}.padding(.leading, 16).padding(.trailing,16)
|
||||
}
|
||||
}
|
||||
if(fullItem.Cast.count != 0) {
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
VStack() {
|
||||
Spacer().frame(height: 8);
|
||||
Text(fullItem.Overview).font(.footnote).padding(.top, 3).fixedSize(horizontal: false, vertical: true).padding(.bottom, 3).padding(.leading, 16).padding(.trailing,16)
|
||||
if(fullItem.Genres.count != 0) {
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
HStack() {
|
||||
Spacer().frame(width: 16)
|
||||
ForEach(fullItem.Cast, id: \.Id) { cast in
|
||||
NavigationLink(destination: LibraryView(extraParams: "&PersonIds=\(cast.Id)", title: cast.Name)) {
|
||||
VStack() {
|
||||
WebImage(url: cast.Image)
|
||||
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
|
||||
.placeholder {
|
||||
Image(uiImage: UIImage(blurHash: (cast.ImageBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : cast.ImageBlurHash), size: CGSize(width: 32, height: 32))!)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: 100, height: 100)
|
||||
.cornerRadius(10)
|
||||
Text("Genres:").font(.callout).fontWeight(.semibold)
|
||||
ForEach(fullItem.Genres, id: \.Id) {genre in
|
||||
NavigationLink(destination: LibraryView(extraParams: "&Genres=\(genre.Name.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "")", title: genre.Name)) {
|
||||
Text(genre.Name).font(.footnote)
|
||||
}
|
||||
}
|
||||
}.padding(.leading, 16).padding(.trailing,16)
|
||||
}
|
||||
}
|
||||
if(fullItem.Cast.count != 0) {
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
VStack() {
|
||||
Spacer().frame(height: 8);
|
||||
HStack() {
|
||||
Spacer().frame(width: 16)
|
||||
ForEach(fullItem.Cast, id: \.Id) { cast in
|
||||
NavigationLink(destination: LibraryView(extraParams: "&PersonIds=\(cast.Id)", title: cast.Name)) {
|
||||
VStack() {
|
||||
WebImage(url: cast.Image)
|
||||
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
|
||||
.placeholder {
|
||||
Image(uiImage: UIImage(blurHash: (cast.ImageBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : cast.ImageBlurHash), size: CGSize(width: 32, height: 32))!)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: 100, height: 100)
|
||||
.cornerRadius(10)
|
||||
}
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: 100, height: 100)
|
||||
.cornerRadius(10).shadow(radius: 6)
|
||||
Text(cast.Name).font(.footnote).fontWeight(.regular).lineLimit(1).frame(width: 100).foregroundColor(Color.primary)
|
||||
if(cast.Role != "") {
|
||||
Text(cast.Role).font(.caption).fontWeight(.medium).lineLimit(1).foregroundColor(Color.secondary).frame(width: 100)
|
||||
}
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: 100, height: 100)
|
||||
.cornerRadius(10).shadow(radius: 6)
|
||||
Text(cast.Name).font(.footnote).fontWeight(.regular).lineLimit(1).frame(width: 100).foregroundColor(Color.primary)
|
||||
if(cast.Role != "") {
|
||||
Text(cast.Role).font(.caption).fontWeight(.medium).lineLimit(1).foregroundColor(Color.secondary).frame(width: 100)
|
||||
}
|
||||
}
|
||||
Spacer().frame(width: 10)
|
||||
}
|
||||
Spacer().frame(width: 10)
|
||||
Spacer().frame(width: 16)
|
||||
}
|
||||
Spacer().frame(width: 16)
|
||||
}
|
||||
}
|
||||
}.padding(.top, -3)
|
||||
}
|
||||
if(fullItem.Directors.count != 0) {
|
||||
HStack() {
|
||||
Text("Directors:").font(.callout).fontWeight(.semibold)
|
||||
Text(fullItem.Directors.joined(separator: ", ")).font(.footnote).lineLimit(1).foregroundColor(Color.secondary)
|
||||
}.padding(.leading, 16).padding(.trailing,16)
|
||||
}
|
||||
if(fullItem.Writers.count != 0) {
|
||||
HStack() {
|
||||
Text("Writers:").font(.callout).fontWeight(.semibold)
|
||||
Text(fullItem.Writers.joined(separator: ", ")).font(.footnote).lineLimit(1).foregroundColor(Color.secondary)
|
||||
}.padding(.leading, 16).padding(.trailing,16)
|
||||
}
|
||||
if(fullItem.Studios.count != 0) {
|
||||
HStack() {
|
||||
Text("Studios:").font(.callout).fontWeight(.semibold)
|
||||
Text(fullItem.Studios.joined(separator: ", ")).font(.footnote).lineLimit(1).foregroundColor(Color.secondary)
|
||||
}.padding(.leading, 16).padding(.trailing,16)
|
||||
}
|
||||
Spacer().frame(height: 3)
|
||||
}
|
||||
}
|
||||
}.padding(EdgeInsets(top: 24, leading: 0, bottom: 0, trailing: 0))
|
||||
}.padding(.top, -3)
|
||||
}
|
||||
if(fullItem.Directors.count != 0) {
|
||||
HStack() {
|
||||
Text("Directors:").font(.callout).fontWeight(.semibold)
|
||||
Text(fullItem.Directors.joined(separator: ", ")).font(.footnote).lineLimit(1).foregroundColor(Color.secondary)
|
||||
}.padding(.leading, 16).padding(.trailing,16)
|
||||
}
|
||||
if(fullItem.Writers.count != 0) {
|
||||
HStack() {
|
||||
Text("Writers:").font(.callout).fontWeight(.semibold)
|
||||
Text(fullItem.Writers.joined(separator: ", ")).font(.footnote).lineLimit(1).foregroundColor(Color.secondary)
|
||||
}.padding(.leading, 16).padding(.trailing,16)
|
||||
}
|
||||
if(fullItem.Studios.count != 0) {
|
||||
HStack() {
|
||||
Text("Studios:").font(.callout).fontWeight(.semibold)
|
||||
Text(fullItem.Studios.joined(separator: ", ")).font(.footnote).lineLimit(1).foregroundColor(Color.secondary)
|
||||
}.padding(.leading, 16).padding(.trailing,16)
|
||||
}
|
||||
Spacer().frame(height: 195);
|
||||
}.frame(maxHeight: .infinity)
|
||||
}.padding(.trailing, 55)
|
||||
}.padding(.top, 12)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.navigationTitle("Movie Details")
|
||||
.navigationTitle(fullItem.Name)
|
||||
.supportedOrientations(.allButUpsideDown)
|
||||
.prefersHomeIndicatorAutoHidden(false)
|
||||
.withHostingWindow() { window in
|
||||
|
|
|
@ -69,46 +69,48 @@ struct NextUpView: View {
|
|||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
Text("Next Up").font(.title2).fontWeight(.bold).padding(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16))
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
HStack() {
|
||||
if(isLoading == false) {
|
||||
Spacer().frame(width:18)
|
||||
ForEach(resumeItems, id: \.Id) { item in
|
||||
NavigationLink(destination: ItemView(item: item)) {
|
||||
VStack(alignment: .leading) {
|
||||
Spacer().frame(height:10)
|
||||
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.SeriesId ?? "")/Images/\(item.ImageType)?fillWidth=300&fillHeight=450&quality=90&tag=\(item.Image)")!)
|
||||
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
|
||||
.placeholder {
|
||||
Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 32, height: 32))!)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.cornerRadius(10)
|
||||
}
|
||||
.frame(width: 100, height: 150)
|
||||
.cornerRadius(10)
|
||||
.shadow(radius: 6)
|
||||
Text(item.SeriesName ?? "")
|
||||
.font(.caption)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.primary)
|
||||
.lineLimit(1)
|
||||
Text("S\(String(item.ParentIndexNumber ?? 0)):E\(String(item.IndexNumber ?? 0))")
|
||||
.font(.caption)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.secondary)
|
||||
.lineLimit(1)
|
||||
Spacer().frame(height:5)
|
||||
if(resumeItems.count != 0) {
|
||||
Text("Next Up").font(.title2).fontWeight(.bold).padding(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16))
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
HStack() {
|
||||
if(isLoading == false) {
|
||||
Spacer().frame(width:18)
|
||||
ForEach(resumeItems, id: \.Id) { item in
|
||||
NavigationLink(destination: ItemView(item: item)) {
|
||||
VStack(alignment: .leading) {
|
||||
Spacer().frame(height:10)
|
||||
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.SeriesId ?? "")/Images/\(item.ImageType)?fillWidth=300&fillHeight=450&quality=90&tag=\(item.Image)")!)
|
||||
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
|
||||
.placeholder {
|
||||
Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 32, height: 32))!)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.cornerRadius(10)
|
||||
}
|
||||
.frame(width: 100, height: 150)
|
||||
.cornerRadius(10)
|
||||
.shadow(radius: 6)
|
||||
Text(item.SeriesName ?? "")
|
||||
.font(.caption)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.primary)
|
||||
.lineLimit(1)
|
||||
Text("S\(String(item.ParentIndexNumber ?? 0)):E\(String(item.IndexNumber ?? 0))")
|
||||
.font(.caption)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.secondary)
|
||||
.lineLimit(1)
|
||||
Spacer().frame(height:5)
|
||||
}
|
||||
.frame(width: 100)
|
||||
Spacer().frame(width:12)
|
||||
}
|
||||
.frame(width: 100)
|
||||
Spacer().frame(width:12)
|
||||
}
|
||||
Spacer().frame(width:18)
|
||||
}
|
||||
Spacer().frame(width:18)
|
||||
}
|
||||
}
|
||||
}.padding(EdgeInsets(top: -2, leading: 0, bottom: 0, trailing: 0))
|
||||
}.padding(EdgeInsets(top: -2, leading: 0, bottom: 0, trailing: 0))
|
||||
}
|
||||
}.onAppear(perform: onAppear).padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,13 +8,22 @@
|
|||
import SwiftUI
|
||||
|
||||
struct SettingsView: View {
|
||||
@Binding var close: Bool;
|
||||
var body: some View {
|
||||
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
|
||||
}
|
||||
}
|
||||
|
||||
struct SettingsView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
SettingsView()
|
||||
NavigationView() {
|
||||
Text("SettingsView not implemented.")
|
||||
.navigationBarTitle("Settings", displayMode: .inline)
|
||||
.toolbar {
|
||||
ToolbarItemGroup(placement: .navigationBarLeading) {
|
||||
Button {
|
||||
close = false
|
||||
} label: {
|
||||
HStack() {
|
||||
Text("Back").font(.callout)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue