Add deeplinking from homepage
|
@ -420,7 +420,8 @@
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = me.vigue.JellyfinPlayer;
|
MARKETING_VERSION = 0.1.0;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = me.vigue.jellyfin;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
@ -443,7 +444,8 @@
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = me.vigue.JellyfinPlayer;
|
MARKETING_VERSION = 0.1.0;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = me.vigue.jellyfin;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
|
|
@ -1,41 +1,49 @@
|
||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
|
"filename" : "Icon-Spotlight-42.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "20x20"
|
"size" : "20x20"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "Icon-60.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "3x",
|
"scale" : "3x",
|
||||||
"size" : "20x20"
|
"size" : "20x20"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "Icon-Small@2x.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "29x29"
|
"size" : "29x29"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "Icon-Small@3x.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "3x",
|
"scale" : "3x",
|
||||||
"size" : "29x29"
|
"size" : "29x29"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "Icon-Spotlight-40@2x.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "40x40"
|
"size" : "40x40"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "Icon-Spotlight-40@3x.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "3x",
|
"scale" : "3x",
|
||||||
"size" : "40x40"
|
"size" : "40x40"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "Icon-60@2x.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "60x60"
|
"size" : "60x60"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "Icon-60@3x.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "3x",
|
"scale" : "3x",
|
||||||
"size" : "60x60"
|
"size" : "60x60"
|
||||||
|
@ -46,46 +54,55 @@
|
||||||
"size" : "20x20"
|
"size" : "20x20"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "Icon-Spotlight-41.png",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "20x20"
|
"size" : "20x20"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "Icon-Small.png",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"scale" : "1x",
|
"scale" : "1x",
|
||||||
"size" : "29x29"
|
"size" : "29x29"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "Icon-Small@2x-1.png",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "29x29"
|
"size" : "29x29"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "Icon-Spotlight-40.png",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"scale" : "1x",
|
"scale" : "1x",
|
||||||
"size" : "40x40"
|
"size" : "40x40"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "Icon-Spotlight-40@2x-1.png",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "40x40"
|
"size" : "40x40"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "Icon-76.png",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"scale" : "1x",
|
"scale" : "1x",
|
||||||
"size" : "76x76"
|
"size" : "76x76"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "Icon-76@2x.png",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "76x76"
|
"size" : "76x76"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "Icon-iPadPro@2x.png",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "83.5x83.5"
|
"size" : "83.5x83.5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"filename" : "Icon.png",
|
||||||
"idiom" : "ios-marketing",
|
"idiom" : "ios-marketing",
|
||||||
"scale" : "1x",
|
"scale" : "1x",
|
||||||
"size" : "1024x1024"
|
"size" : "1024x1024"
|
||||||
|
|
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 8.1 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 4.7 KiB |
After Width: | Height: | Size: 4.7 KiB |
After Width: | Height: | Size: 7.5 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 232 KiB |
|
@ -157,8 +157,8 @@ struct ConnectToServerView: View {
|
||||||
do {
|
do {
|
||||||
try viewContext.save()
|
try viewContext.save()
|
||||||
print("Saved to Core Data Store")
|
print("Saved to Core Data Store")
|
||||||
jsi.did = true
|
|
||||||
_rootIsActive.wrappedValue = false
|
_rootIsActive.wrappedValue = false
|
||||||
|
jsi.did = true
|
||||||
} catch {
|
} catch {
|
||||||
// Replace this implementation with code to handle the error appropriately.
|
// Replace this implementation with code to handle the error appropriately.
|
||||||
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
|
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
|
||||||
|
|
|
@ -271,71 +271,82 @@ struct ContentView: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
LoadingView(isShowing: $isLoading) {
|
if(!jsi.did) {
|
||||||
TabView(selection: $tabSelection) {
|
LoadingView(isShowing: $isLoading) {
|
||||||
NavigationView() {
|
TabView(selection: $tabSelection) {
|
||||||
VStack {
|
NavigationView() {
|
||||||
NavigationLink(destination: ConnectToServerView(isActive: $needsToSelectServer), isActive: $needsToSelectServer) {
|
VStack {
|
||||||
EmptyView()
|
NavigationLink(destination: ConnectToServerView(isActive: $needsToSelectServer), isActive: $needsToSelectServer) {
|
||||||
}.isDetailLink(false)
|
EmptyView()
|
||||||
NavigationLink(destination: ConnectToServerView(skip_server: true, skip_server_prefill: globalData.server, reauth_deviceId: globalData.user?.device_uuid ?? "", isActive: $isSignInErrored), isActive: $isSignInErrored) {
|
}.isDetailLink(false)
|
||||||
EmptyView()
|
NavigationLink(destination: ConnectToServerView(skip_server: true, skip_server_prefill: globalData.server, reauth_deviceId: globalData.user?.device_uuid ?? "", isActive: $isSignInErrored), isActive: $isSignInErrored) {
|
||||||
}.isDetailLink(false)
|
EmptyView()
|
||||||
if(!needsToSelectServer && !isSignInErrored) {
|
}.isDetailLink(false)
|
||||||
VStack(alignment: .leading) {
|
if(!needsToSelectServer && !isSignInErrored) {
|
||||||
ScrollView() {
|
VStack(alignment: .leading) {
|
||||||
Spacer().frame(height: self.isPortrait ? 0 : 15)
|
ScrollView() {
|
||||||
ContinueWatchingView()
|
Spacer().frame(height: self.isPortrait ? 0 : 15)
|
||||||
NextUpView().padding(EdgeInsets(top: 4, leading: 0, bottom: 0, trailing: 0))
|
ContinueWatchingView()
|
||||||
ForEach(librariesShowRecentlyAdded, id: \.self) { library_id in
|
NextUpView().padding(EdgeInsets(top: 4, leading: 0, bottom: 0, trailing: 0))
|
||||||
VStack(alignment: .leading) {
|
ForEach(librariesShowRecentlyAdded, id: \.self) { library_id in
|
||||||
HStack() {
|
VStack(alignment: .leading) {
|
||||||
Text("Latest \(library_names[library_id] ?? "")").font(.title2).fontWeight(.bold).padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 16))
|
HStack() {
|
||||||
Spacer()
|
Text("Latest \(library_names[library_id] ?? "")").font(.title2).fontWeight(.bold).padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 16))
|
||||||
NavigationLink(destination: LibraryView(prefill: library_id, names: library_names, libraries: libraries, filter: "&SortBy=DateCreated&SortOrder=Descending")) {
|
Spacer()
|
||||||
Text("See All").font(.subheadline).fontWeight(.bold)
|
NavigationLink(destination: LibraryView(prefill: library_id, names: library_names, libraries: libraries, filter: "&SortBy=DateCreated&SortOrder=Descending")) {
|
||||||
}
|
Text("See All").font(.subheadline).fontWeight(.bold)
|
||||||
}.padding(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16))
|
}
|
||||||
LatestMediaView(library: library_id)
|
}.padding(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16))
|
||||||
}.padding(EdgeInsets(top: 4, leading: 0, bottom: 0, trailing: 0))
|
LatestMediaView(library: library_id)
|
||||||
|
}.padding(EdgeInsets(top: 4, leading: 0, bottom: 0, trailing: 0))
|
||||||
|
}
|
||||||
|
Spacer().frame(height: 7)
|
||||||
}
|
}
|
||||||
Spacer().frame(height: 7)
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.navigationTitle("Home")
|
||||||
|
.toolbar {
|
||||||
|
ToolbarItemGroup(placement: .navigationBarTrailing) {
|
||||||
|
Button {
|
||||||
|
print("Settings tapped!")
|
||||||
|
} label: {
|
||||||
|
Image(systemName: "gear")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationTitle("Home")
|
.tabItem({
|
||||||
.toolbar {
|
Text("Home")
|
||||||
ToolbarItemGroup(placement: .navigationBarTrailing) {
|
Image(systemName: "house")
|
||||||
Button {
|
})
|
||||||
print("Settings tapped!")
|
.tag("Home")
|
||||||
} label: {
|
NavigationView() {
|
||||||
Image(systemName: "gear")
|
LibraryView(prefill: "", names: library_names, libraries: libraries)
|
||||||
}
|
.navigationTitle("Library")
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
.tabItem({
|
||||||
|
Text("All Media")
|
||||||
|
Image(systemName: "folder")
|
||||||
|
})
|
||||||
|
.tag("All Media")
|
||||||
|
|
||||||
}
|
}
|
||||||
.tabItem({
|
}.environmentObject(globalData)
|
||||||
Text("Home")
|
.onAppear(perform: startup)
|
||||||
Image(systemName: "house")
|
.navigationViewStyle(StackNavigationViewStyle())
|
||||||
})
|
.alert(isPresented: $isNetworkErrored) {
|
||||||
.tag("Home")
|
Alert(title: Text("Network Error"), message: Text("Couldn't connect to Jellyfin"), dismissButton: .default(Text("Ok")))
|
||||||
NavigationView() {
|
|
||||||
LibraryView(prefill: "", names: library_names, libraries: libraries)
|
|
||||||
.navigationTitle("Library")
|
|
||||||
}
|
|
||||||
.tabItem({
|
|
||||||
Text("All Media")
|
|
||||||
Image(systemName: "folder")
|
|
||||||
})
|
|
||||||
.tag("All Media")
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}.environmentObject(globalData)
|
} else {
|
||||||
.onAppear(perform: startup)
|
Text("Signing in...")
|
||||||
.navigationViewStyle(StackNavigationViewStyle())
|
.onAppear(perform: {
|
||||||
.alert(isPresented: $isNetworkErrored) {
|
DispatchQueue.global(qos: .userInitiated).async { [self] in
|
||||||
Alert(title: Text("Network Error"), message: Text("Couldn't connect to Jellyfin"), dismissButton: .default(Text("Ok")))
|
print("Signing in")
|
||||||
|
sleep(3)
|
||||||
|
jsi.did = false
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,62 +81,64 @@ struct ContinueWatchingView: View {
|
||||||
if(isLoading == false) {
|
if(isLoading == false) {
|
||||||
Spacer().frame(width:16)
|
Spacer().frame(width:16)
|
||||||
ForEach(resumeItems, id: \.Id) { item in
|
ForEach(resumeItems, id: \.Id) { item in
|
||||||
VStack(alignment: .leading) {
|
NavigationLink(destination: ItemView(item: item)) {
|
||||||
Spacer().frame(height: 10)
|
VStack(alignment: .leading) {
|
||||||
if(item.Type == "Episode") {
|
Spacer().frame(height: 10)
|
||||||
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?fillWidth=560&fillHeight=315&quality=90&tag=\(item.Image)")!)
|
if(item.Type == "Episode") {
|
||||||
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
|
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?fillWidth=560&fillHeight=315&quality=90&tag=\(item.Image)")!)
|
||||||
.placeholder {
|
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
|
||||||
Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 32, height: 32))!)
|
.placeholder {
|
||||||
.resizable()
|
Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 32, height: 32))!)
|
||||||
.scaledToFit()
|
.resizable()
|
||||||
.cornerRadius(10)
|
.scaledToFit()
|
||||||
}
|
.cornerRadius(10)
|
||||||
.frame(width: 320, height: 180)
|
}
|
||||||
.cornerRadius(10)
|
.frame(width: 320, height: 180)
|
||||||
.overlay(
|
.cornerRadius(10)
|
||||||
ZStack {
|
.overlay(
|
||||||
Text("S\(String(item.ParentIndexNumber ?? 0)):E\(String(item.IndexNumber ?? 0)) - \(item.Name)")
|
ZStack {
|
||||||
.font(.caption)
|
Text("S\(String(item.ParentIndexNumber ?? 0)):E\(String(item.IndexNumber ?? 0)) - \(item.Name)")
|
||||||
.padding(6)
|
.font(.caption)
|
||||||
.foregroundColor(.white)
|
.padding(6)
|
||||||
}.background(Color.black)
|
.foregroundColor(.white)
|
||||||
.opacity(0.8)
|
}.background(Color.black)
|
||||||
.cornerRadius(10.0)
|
.opacity(0.8)
|
||||||
.padding(6), alignment: .topTrailing
|
.cornerRadius(10.0)
|
||||||
)
|
.padding(6), alignment: .topTrailing
|
||||||
.overlay(
|
)
|
||||||
RoundedRectangle(cornerRadius: 10, style: .circular)
|
.overlay(
|
||||||
.fill(Color(red: 172/255, green: 92/255, blue: 195/255).opacity(0.4))
|
RoundedRectangle(cornerRadius: 10, style: .circular)
|
||||||
.frame(width: CGFloat((item.ItemProgress/100)*320), height: 180)
|
.fill(Color(red: 172/255, green: 92/255, blue: 195/255).opacity(0.4))
|
||||||
.padding(0), alignment: .bottomLeading
|
.frame(width: CGFloat((item.ItemProgress/100)*320), height: 180)
|
||||||
)
|
.padding(0), alignment: .bottomLeading
|
||||||
.shadow(radius: 5)
|
)
|
||||||
} else {
|
.shadow(radius: 5)
|
||||||
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?fillWidth=560&fillHeight=315&quality=90&tag=\(item.Image)")!)
|
} else {
|
||||||
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
|
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?fillWidth=560&fillHeight=315&quality=90&tag=\(item.Image)")!)
|
||||||
.placeholder {
|
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
|
||||||
Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 32, height: 32))!)
|
.placeholder {
|
||||||
.resizable()
|
Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 32, height: 32))!)
|
||||||
.scaledToFit()
|
.resizable()
|
||||||
.cornerRadius(10)
|
.scaledToFit()
|
||||||
}
|
.cornerRadius(10)
|
||||||
.frame(width: 320, height: 180)
|
}
|
||||||
.cornerRadius(10)
|
.frame(width: 320, height: 180)
|
||||||
.overlay(
|
.cornerRadius(10)
|
||||||
RoundedRectangle(cornerRadius: 10, style: .circular)
|
.overlay(
|
||||||
.fill(Color(red: 172/255, green: 92/255, blue: 195/255).opacity(0.4))
|
RoundedRectangle(cornerRadius: 10, style: .circular)
|
||||||
.frame(width: CGFloat((item.ItemProgress/100)*320), height: 180)
|
.fill(Color(red: 172/255, green: 92/255, blue: 195/255).opacity(0.4))
|
||||||
.padding(0), alignment: .bottomLeading
|
.frame(width: CGFloat((item.ItemProgress/100)*320), height: 180)
|
||||||
)
|
.padding(0), alignment: .bottomLeading
|
||||||
.shadow(radius: 5)
|
)
|
||||||
}
|
.shadow(radius: 5)
|
||||||
Text("\(item.Type == "Episode" ? item.SeriesName ?? "" : item.Name)")
|
}
|
||||||
.font(.callout)
|
Text("\(item.Type == "Episode" ? item.SeriesName ?? "" : item.Name)")
|
||||||
.fontWeight(.semibold)
|
.font(.callout)
|
||||||
.foregroundColor(.primary)
|
.fontWeight(.semibold)
|
||||||
Spacer().frame(height: 5)
|
.foregroundColor(.primary)
|
||||||
}.padding(.trailing, 5)
|
Spacer().frame(height: 5)
|
||||||
|
}.padding(.trailing, 5)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Spacer().frame(width:14)
|
Spacer().frame(width:14)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
<key>CFBundleDisplayName</key>
|
<key>CFBundleDisplayName</key>
|
||||||
<string>Jellyfin iOS</string>
|
<string>Jellyfin</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>$(EXECUTABLE_NAME)</string>
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.0</string>
|
<string>$(MARKETING_VERSION)</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1</string>
|
<string>1</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
|
|
|
@ -18,22 +18,13 @@ struct JellyfinPlayerApp: App {
|
||||||
|
|
||||||
var body: some Scene {
|
var body: some Scene {
|
||||||
WindowGroup {
|
WindowGroup {
|
||||||
if(!jsi.did) {
|
ContentView()
|
||||||
ContentView()
|
.environment(\.managedObjectContext, persistenceController.container.viewContext)
|
||||||
.environment(\.managedObjectContext, persistenceController.container.viewContext)
|
.environmentObject(jsi)
|
||||||
.environmentObject(jsi)
|
.withHostingWindow() { window in
|
||||||
.withHostingWindow() { window in
|
window?.rootViewController = PreferenceUIHostingController(wrappedView: ContentView().environment(\.managedObjectContext, persistenceController.container.viewContext)
|
||||||
window?.rootViewController = PreferenceUIHostingController(wrappedView: ContentView().environment(\.managedObjectContext, persistenceController.container.viewContext)
|
.environmentObject(jsi))
|
||||||
.environmentObject(jsi))
|
}
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Text("Please wait...")
|
|
||||||
.onAppear(perform: {
|
|
||||||
print("Signing in")
|
|
||||||
sleep(1)
|
|
||||||
jsi.did = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,51 +87,53 @@ struct LatestMediaView: View {
|
||||||
HStack() {
|
HStack() {
|
||||||
Spacer().frame(width:18)
|
Spacer().frame(width:18)
|
||||||
ForEach(resumeItems, id: \.Id) { item in
|
ForEach(resumeItems, id: \.Id) { item in
|
||||||
VStack(alignment: .leading) {
|
NavigationLink(destination: ItemView(item: item)) {
|
||||||
if(item.Type == "Series") {
|
VStack(alignment: .leading) {
|
||||||
Spacer().frame(height:10)
|
if(item.Type == "Series") {
|
||||||
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?fillWidth=300&fillHeight=450&quality=90&tag=\(item.Image)")!)
|
Spacer().frame(height:10)
|
||||||
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
|
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?fillWidth=300&fillHeight=450&quality=90&tag=\(item.Image)")!)
|
||||||
.placeholder {
|
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
|
||||||
Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 32, height: 32))!)
|
.placeholder {
|
||||||
.resizable()
|
Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 32, height: 32))!)
|
||||||
.scaledToFit()
|
.resizable()
|
||||||
.cornerRadius(10)
|
.scaledToFit()
|
||||||
}
|
.cornerRadius(10)
|
||||||
.frame(width: 100, height: 150)
|
}
|
||||||
.cornerRadius(10)
|
.frame(width: 100, height: 150)
|
||||||
.overlay(
|
.cornerRadius(10)
|
||||||
ZStack {
|
.overlay(
|
||||||
Text("\(String(item.ItemBadge ?? 0))")
|
ZStack {
|
||||||
.font(.caption)
|
Text("\(String(item.ItemBadge ?? 0))")
|
||||||
.padding(3)
|
.font(.caption)
|
||||||
.foregroundColor(.white)
|
.padding(3)
|
||||||
}.background(Color.black)
|
.foregroundColor(.white)
|
||||||
.opacity(0.8)
|
}.background(Color.black)
|
||||||
.cornerRadius(10.0)
|
.opacity(0.8)
|
||||||
.padding(3), alignment: .topTrailing
|
.cornerRadius(10.0)
|
||||||
).shadow(radius: 6)
|
.padding(3), alignment: .topTrailing
|
||||||
} else {
|
).shadow(radius: 6)
|
||||||
Spacer().frame(height:10)
|
} else {
|
||||||
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?fillWidth=300&fillHeight=450&quality=90&tag=\(item.Image)")!)
|
Spacer().frame(height:10)
|
||||||
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
|
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?fillWidth=300&fillHeight=450&quality=90&tag=\(item.Image)")!)
|
||||||
.placeholder {
|
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
|
||||||
Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 32, height: 32))!)
|
.placeholder {
|
||||||
.resizable()
|
Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 32, height: 32))!)
|
||||||
.scaledToFit()
|
.resizable()
|
||||||
.cornerRadius(10)
|
.scaledToFit()
|
||||||
}
|
.cornerRadius(10)
|
||||||
.frame(width: 100, height: 150)
|
}
|
||||||
.cornerRadius(10)
|
.frame(width: 100, height: 150)
|
||||||
.shadow(radius: 6)
|
.cornerRadius(10)
|
||||||
}
|
.shadow(radius: 6)
|
||||||
Text(item.Name)
|
}
|
||||||
.font(.caption)
|
Text(item.Name)
|
||||||
.fontWeight(.semibold)
|
.font(.caption)
|
||||||
.foregroundColor(.primary)
|
.fontWeight(.semibold)
|
||||||
.lineLimit(1)
|
.foregroundColor(.primary)
|
||||||
Spacer().frame(height:5)
|
.lineLimit(1)
|
||||||
}.frame(width: 100)
|
Spacer().frame(height:5)
|
||||||
|
}.frame(width: 100)
|
||||||
|
}
|
||||||
Spacer().frame(width: 14)
|
Spacer().frame(width: 14)
|
||||||
}
|
}
|
||||||
Spacer().frame(width:18)
|
Spacer().frame(width:18)
|
||||||
|
|
|
@ -32,7 +32,7 @@ struct LibrarySearchView: View {
|
||||||
func onAppear() {
|
func onAppear() {
|
||||||
_isLoading.wrappedValue = true;
|
_isLoading.wrappedValue = true;
|
||||||
_items.wrappedValue = [];
|
_items.wrappedValue = [];
|
||||||
let request = RestRequest(method: .get, url: (globalData.server?.baseURI ?? "") + _url.wrappedValue + "&searchTerm=" + searchQuery)
|
let request = RestRequest(method: .get, url: (globalData.server?.baseURI ?? "") + _url.wrappedValue + "&searchTerm=" + searchQuery.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!)
|
||||||
request.headerParameters["X-Emby-Authorization"] = globalData.authHeader
|
request.headerParameters["X-Emby-Authorization"] = globalData.authHeader
|
||||||
request.contentType = "application/json"
|
request.contentType = "application/json"
|
||||||
request.acceptType = "application/json"
|
request.acceptType = "application/json"
|
||||||
|
|
|
@ -274,9 +274,7 @@ struct LibraryView: View {
|
||||||
}.onAppear(perform: listOnAppear).overrideViewPreference(.unspecified).navigationTitle("All Media")
|
}.onAppear(perform: listOnAppear).overrideViewPreference(.unspecified).navigationTitle("All Media")
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItemGroup(placement: .navigationBarTrailing) {
|
ToolbarItemGroup(placement: .navigationBarTrailing) {
|
||||||
Button {
|
NavigationLink(destination: LibrarySearchView(url: "/Users/\(globalData.user?.user_id ?? "")/Items?Limit=60&StartIndex=0&Recursive=true&Fields=PrimaryImageAspectRatio%2CBasicSyncInfo&ImageTypeLimit=1&EnableImageTypes=Primary%2CBackdrop%2CThumb%2CBanner&IncludeItemTypes=Movie,Series\(extraParam)", close: $closeSearch), isActive: $closeSearch) {
|
||||||
print("Search tapped!")
|
|
||||||
} label: {
|
|
||||||
Image(systemName: "magnifyingglass")
|
Image(systemName: "magnifyingglass")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,28 +75,35 @@ struct NextUpView: View {
|
||||||
if(isLoading == false) {
|
if(isLoading == false) {
|
||||||
Spacer().frame(width:18)
|
Spacer().frame(width:18)
|
||||||
ForEach(resumeItems, id: \.Id) { item in
|
ForEach(resumeItems, id: \.Id) { item in
|
||||||
VStack(alignment: .leading) {
|
NavigationLink(destination: ItemView(item: item)) {
|
||||||
Spacer().frame(height:10)
|
VStack(alignment: .leading) {
|
||||||
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.SeriesId ?? "")/Images/\(item.ImageType)?fillWidth=300&fillHeight=450&quality=90&tag=\(item.Image)")!)
|
Spacer().frame(height:10)
|
||||||
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
|
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.SeriesId ?? "")/Images/\(item.ImageType)?fillWidth=300&fillHeight=450&quality=90&tag=\(item.Image)")!)
|
||||||
.placeholder {
|
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
|
||||||
Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 32, height: 32))!)
|
.placeholder {
|
||||||
.resizable()
|
Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 32, height: 32))!)
|
||||||
.scaledToFit()
|
.resizable()
|
||||||
.cornerRadius(10)
|
.scaledToFit()
|
||||||
}
|
.cornerRadius(10)
|
||||||
.frame(width: 100, height: 150)
|
}
|
||||||
.cornerRadius(10)
|
.frame(width: 100, height: 150)
|
||||||
.shadow(radius: 6)
|
.cornerRadius(10)
|
||||||
Text(item.SeriesName ?? "")
|
.shadow(radius: 6)
|
||||||
.font(.caption)
|
Text(item.SeriesName ?? "")
|
||||||
.fontWeight(.semibold)
|
.font(.caption)
|
||||||
.foregroundColor(.primary)
|
.fontWeight(.semibold)
|
||||||
.lineLimit(1)
|
.foregroundColor(.primary)
|
||||||
Spacer().frame(height:5)
|
.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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,15 +100,13 @@ struct PlayerDemo: View {
|
||||||
_inactivity.wrappedValue = true
|
_inactivity.wrappedValue = true
|
||||||
}
|
}
|
||||||
if((lastPosition == Double(vlcplayer.position) && vlcplayer.state != VLCMediaPlayerState.paused)) {
|
if((lastPosition == Double(vlcplayer.position) && vlcplayer.state != VLCMediaPlayerState.paused)) {
|
||||||
if(iterations > 3) {
|
if(iterations > 5) {
|
||||||
_iterations.wrappedValue = 0;
|
_iterations.wrappedValue = 0;
|
||||||
_streamLoading.wrappedValue = true;
|
_streamLoading.wrappedValue = true;
|
||||||
print("Buffering")
|
|
||||||
}
|
}
|
||||||
_iterations.wrappedValue+=1;
|
_iterations.wrappedValue+=1;
|
||||||
} else {
|
} else {
|
||||||
_iterations.wrappedValue = 0;
|
_iterations.wrappedValue = 0;
|
||||||
print("Not Buffering")
|
|
||||||
_streamLoading.wrappedValue = false;
|
_streamLoading.wrappedValue = false;
|
||||||
}
|
}
|
||||||
if(vlcplayer.state == VLCMediaPlayerState.error) {
|
if(vlcplayer.state == VLCMediaPlayerState.error) {
|
||||||
|
@ -204,7 +202,7 @@ struct PlayerDemo: View {
|
||||||
request.headerParameters["X-Emby-Authorization"] = globalData.authHeader
|
request.headerParameters["X-Emby-Authorization"] = globalData.authHeader
|
||||||
request.contentType = "application/json"
|
request.contentType = "application/json"
|
||||||
request.acceptType = "application/json"
|
request.acceptType = "application/json"
|
||||||
request.messageBody = "{\"DeviceProfile\":{\"MaxStreamingBitrate\":120000000,\"MaxStaticBitrate\":100000000,\"MusicStreamingTranscodingBitrate\":384000,\"DirectPlayProfiles\":[{\"Container\":\"webm\",\"Type\":\"Video\",\"VideoCodec\":\"vp8,vp9\",\"AudioCodec\":\"vorbis\"},{\"Container\":\"mp4,m4v,mkv\",\"Type\":\"Video\",\"VideoCodec\":\"hevc,h264,vp8,vp9\",\"AudioCodec\":\"aac,mp3,ac3,eac3,flac,alac,vorbis,dts\"},{\"Container\":\"mov\",\"Type\":\"Video\",\"VideoCodec\":\"h264\",\"AudioCodec\":\"aac,mp3,ac3,eac3,flac,alac,vorbis\"},{\"Container\":\"mp3\",\"Type\":\"Audio\"},{\"Container\":\"aac\",\"Type\":\"Audio\"},{\"Container\":\"m4a\",\"AudioCodec\":\"aac\",\"Type\":\"Audio\"},{\"Container\":\"m4b\",\"AudioCodec\":\"aac\",\"Type\":\"Audio\"},{\"Container\":\"flac\",\"Type\":\"Audio\"},{\"Container\":\"alac\",\"Type\":\"Audio\"},{\"Container\":\"m4a\",\"AudioCodec\":\"alac\",\"Type\":\"Audio\"},{\"Container\":\"m4b\",\"AudioCodec\":\"alac\",\"Type\":\"Audio\"},{\"Container\":\"webma\",\"Type\":\"Audio\"},{\"Container\":\"webm\",\"AudioCodec\":\"webma\",\"Type\":\"Audio\"},{\"Container\":\"wav\",\"Type\":\"Audio\"}],\"TranscodingProfiles\":[{\"Container\":\"aac\",\"Type\":\"Audio\",\"AudioCodec\":\"aac\",\"Context\":\"Streaming\",\"Protocol\":\"hls\",\"MaxAudioChannels\":\"6\",\"MinSegments\":\"2\",\"BreakOnNonKeyFrames\":true},{\"Container\":\"aac\",\"Type\":\"Audio\",\"AudioCodec\":\"aac\",\"Context\":\"Streaming\",\"Protocol\":\"http\",\"MaxAudioChannels\":\"6\"},{\"Container\":\"mp3\",\"Type\":\"Audio\",\"AudioCodec\":\"mp3\",\"Context\":\"Streaming\",\"Protocol\":\"http\",\"MaxAudioChannels\":\"6\"},{\"Container\":\"wav\",\"Type\":\"Audio\",\"AudioCodec\":\"wav\",\"Context\":\"Streaming\",\"Protocol\":\"http\",\"MaxAudioChannels\":\"6\"},{\"Container\":\"mp3\",\"Type\":\"Audio\",\"AudioCodec\":\"mp3\",\"Context\":\"Static\",\"Protocol\":\"http\",\"MaxAudioChannels\":\"6\"},{\"Container\":\"aac\",\"Type\":\"Audio\",\"AudioCodec\":\"aac\",\"Context\":\"Static\",\"Protocol\":\"http\",\"MaxAudioChannels\":\"6\"},{\"Container\":\"wav\",\"Type\":\"Audio\",\"AudioCodec\":\"wav\",\"Context\":\"Static\",\"Protocol\":\"http\",\"MaxAudioChannels\":\"6\"},{\"Container\":\"ts\",\"Type\":\"Video\",\"AudioCodec\":\"aac,mp3,ac3,eac3\",\"VideoCodec\":\"h264\",\"Context\":\"Streaming\",\"Protocol\":\"hls\",\"MaxAudioChannels\":\"6\",\"MinSegments\":\"2\",\"BreakOnNonKeyFrames\":true},{\"Container\":\"webm\",\"Type\":\"Video\",\"AudioCodec\":\"vorbis\",\"VideoCodec\":\"vpx\",\"Context\":\"Streaming\",\"Protocol\":\"http\",\"MaxAudioChannels\":\"6\"},{\"Container\":\"mp4\",\"Type\":\"Video\",\"AudioCodec\":\"aac,mp3,ac3,eac3,flac,alac,vorbis\",\"VideoCodec\":\"h264\",\"Context\":\"Static\",\"Protocol\":\"http\"}],\"ContainerProfiles\":[],\"CodecProfiles\":[{\"Type\":\"Video\",\"Codec\":\"h264\",\"Conditions\":[{\"Condition\":\"NotEquals\",\"Property\":\"IsAnamorphic\",\"Value\":\"true\",\"IsRequired\":false},{\"Condition\":\"EqualsAny\",\"Property\":\"VideoProfile\",\"Value\":\"high|main|baseline|constrained baseline\",\"IsRequired\":false},{\"Condition\":\"LessThanEqual\",\"Property\":\"VideoLevel\",\"Value\":\"80\",\"IsRequired\":false},{\"Condition\":\"NotEquals\",\"Property\":\"IsInterlaced\",\"Value\":\"true\",\"IsRequired\":false}]},{\"Type\":\"Video\",\"Codec\":\"hevc\",\"Conditions\":[{\"Condition\":\"NotEquals\",\"Property\":\"IsAnamorphic\",\"Value\":\"true\",\"IsRequired\":false},{\"Condition\":\"EqualsAny\",\"Property\":\"VideoProfile\",\"Value\":\"main|main 10\",\"IsRequired\":false},{\"Condition\":\"LessThanEqual\",\"Property\":\"VideoLevel\",\"Value\":\"190\",\"IsRequired\":false},{\"Condition\":\"NotEquals\",\"Property\":\"IsInterlaced\",\"Value\":\"true\",\"IsRequired\":false}]}],\"SubtitleProfiles\":[{\"Format\":\"vtt\",\"Method\":\"External\"},{\"Format\":\"ass\",\"Method\":\"External\"},{\"Format\":\"ssa\",\"Method\":\"External\"}],\"ResponseProfiles\":[{\"Type\":\"Video\",\"Container\":\"m4v\",\"MimeType\":\"video/mp4\"}]}}".data(using: .ascii);
|
request.messageBody = "{\"DeviceProfile\":{\"MaxStreamingBitrate\":70000000,\"MaxStaticBitrate\":150000000,\"MusicStreamingTranscodingBitrate\":384000,\"DirectPlayProfiles\":[{\"Container\":\"webm\",\"Type\":\"Video\",\"VideoCodec\":\"vp8,vp9\",\"AudioCodec\":\"vorbis\"},{\"Container\":\"mp4,m4v,mkv\",\"Type\":\"Video\",\"VideoCodec\":\"hevc,h264,vp8,vp9\",\"AudioCodec\":\"aac,mp3,ac3,eac3,flac,alac,vorbis,dts\"},{\"Container\":\"mov\",\"Type\":\"Video\",\"VideoCodec\":\"h264\",\"AudioCodec\":\"aac,mp3,ac3,eac3,flac,alac,vorbis\"},{\"Container\":\"mp3\",\"Type\":\"Audio\"},{\"Container\":\"aac\",\"Type\":\"Audio\"},{\"Container\":\"m4a\",\"AudioCodec\":\"aac\",\"Type\":\"Audio\"},{\"Container\":\"m4b\",\"AudioCodec\":\"aac\",\"Type\":\"Audio\"},{\"Container\":\"flac\",\"Type\":\"Audio\"},{\"Container\":\"alac\",\"Type\":\"Audio\"},{\"Container\":\"m4a\",\"AudioCodec\":\"alac\",\"Type\":\"Audio\"},{\"Container\":\"m4b\",\"AudioCodec\":\"alac\",\"Type\":\"Audio\"},{\"Container\":\"webma\",\"Type\":\"Audio\"},{\"Container\":\"webm\",\"AudioCodec\":\"webma\",\"Type\":\"Audio\"},{\"Container\":\"wav\",\"Type\":\"Audio\"}],\"TranscodingProfiles\":[{\"Container\":\"aac\",\"Type\":\"Audio\",\"AudioCodec\":\"aac\",\"Context\":\"Streaming\",\"Protocol\":\"hls\",\"MaxAudioChannels\":\"6\",\"MinSegments\":\"2\",\"BreakOnNonKeyFrames\":true},{\"Container\":\"aac\",\"Type\":\"Audio\",\"AudioCodec\":\"aac\",\"Context\":\"Streaming\",\"Protocol\":\"http\",\"MaxAudioChannels\":\"6\"},{\"Container\":\"mp3\",\"Type\":\"Audio\",\"AudioCodec\":\"mp3\",\"Context\":\"Streaming\",\"Protocol\":\"http\",\"MaxAudioChannels\":\"6\"},{\"Container\":\"wav\",\"Type\":\"Audio\",\"AudioCodec\":\"wav\",\"Context\":\"Streaming\",\"Protocol\":\"http\",\"MaxAudioChannels\":\"6\"},{\"Container\":\"mp3\",\"Type\":\"Audio\",\"AudioCodec\":\"mp3\",\"Context\":\"Static\",\"Protocol\":\"http\",\"MaxAudioChannels\":\"6\"},{\"Container\":\"aac\",\"Type\":\"Audio\",\"AudioCodec\":\"aac\",\"Context\":\"Static\",\"Protocol\":\"http\",\"MaxAudioChannels\":\"6\"},{\"Container\":\"wav\",\"Type\":\"Audio\",\"AudioCodec\":\"wav\",\"Context\":\"Static\",\"Protocol\":\"http\",\"MaxAudioChannels\":\"6\"},{\"Container\":\"ts\",\"Type\":\"Video\",\"AudioCodec\":\"aac,mp3,ac3,eac3\",\"VideoCodec\":\"h264\",\"Context\":\"Streaming\",\"Protocol\":\"hls\",\"MaxAudioChannels\":\"6\",\"MinSegments\":\"2\",\"BreakOnNonKeyFrames\":true},{\"Container\":\"webm\",\"Type\":\"Video\",\"AudioCodec\":\"vorbis\",\"VideoCodec\":\"vpx\",\"Context\":\"Streaming\",\"Protocol\":\"http\",\"MaxAudioChannels\":\"6\"},{\"Container\":\"mp4\",\"Type\":\"Video\",\"AudioCodec\":\"aac,mp3,ac3,eac3,flac,alac,vorbis\",\"VideoCodec\":\"h264\",\"Context\":\"Static\",\"Protocol\":\"http\"}],\"ContainerProfiles\":[],\"CodecProfiles\":[{\"Type\":\"Video\",\"Codec\":\"h264\",\"Conditions\":[{\"Condition\":\"NotEquals\",\"Property\":\"IsAnamorphic\",\"Value\":\"true\",\"IsRequired\":false},{\"Condition\":\"EqualsAny\",\"Property\":\"VideoProfile\",\"Value\":\"high|main|baseline|constrained baseline\",\"IsRequired\":false},{\"Condition\":\"LessThanEqual\",\"Property\":\"VideoLevel\",\"Value\":\"80\",\"IsRequired\":false},{\"Condition\":\"NotEquals\",\"Property\":\"IsInterlaced\",\"Value\":\"true\",\"IsRequired\":false}]},{\"Type\":\"Video\",\"Codec\":\"hevc\",\"Conditions\":[{\"Condition\":\"NotEquals\",\"Property\":\"IsAnamorphic\",\"Value\":\"true\",\"IsRequired\":false},{\"Condition\":\"EqualsAny\",\"Property\":\"VideoProfile\",\"Value\":\"main|main 10\",\"IsRequired\":false},{\"Condition\":\"LessThanEqual\",\"Property\":\"VideoLevel\",\"Value\":\"190\",\"IsRequired\":false},{\"Condition\":\"NotEquals\",\"Property\":\"IsInterlaced\",\"Value\":\"true\",\"IsRequired\":false}]}],\"SubtitleProfiles\":[{\"Format\":\"vtt\",\"Method\":\"External\"},{\"Format\":\"ass\",\"Method\":\"External\"},{\"Format\":\"ssa\",\"Method\":\"External\"},{\"Format\":\"pgssub\",\"Method\":\"Embed\"},{\"Format\":\"pgs\",\"Method\":\"Embed\"},{\"Format\":\"sub\",\"Method\":\"Embed\"}],\"ResponseProfiles\":[{\"Type\":\"Video\",\"Container\":\"m4v\",\"MimeType\":\"video/mp4\"}]}}".data(using: .ascii);
|
||||||
|
|
||||||
request.responseData() { (result: Result<RestResponse<Data>, RestError>) in
|
request.responseData() { (result: Result<RestResponse<Data>, RestError>) in
|
||||||
switch result {
|
switch result {
|
||||||
|
|