added some more graphical things
Some checks are pending
Build and Release IPA / Build IPA (push) Waiting to run

This commit is contained in:
cranci1 2025-02-16 09:47:33 +01:00
parent ce83066ced
commit 083946699d
4 changed files with 117 additions and 117 deletions

View file

@ -42,6 +42,118 @@ struct HomeView: View {
var body: some View {
NavigationView {
ScrollView {
if !continueWatchingItems.isEmpty {
VStack(alignment: .leading) {
Text("Continue Watching")
.font(.headline)
.padding(.horizontal, 8)
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 8) {
ForEach(Array(continueWatchingItems.reversed())) { item in
Button(action: {
if UserDefaults.standard.string(forKey: "externalPlayer") == "Sora" {
let customMediaPlayer = CustomMediaPlayer(
module: item.module,
urlString: item.streamUrl,
fullUrl: item.fullUrl,
title: item.mediaTitle,
episodeNumber: item.episodeNumber,
onWatchNext: { },
subtitlesURL: item.subtitles,
episodeImageUrl: item.imageUrl
)
let hostingController = UIHostingController(rootView: customMediaPlayer)
hostingController.modalPresentationStyle = .fullScreen
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let rootVC = windowScene.windows.first?.rootViewController {
rootVC.present(hostingController, animated: true, completion: nil)
}
} else {
let videoPlayerViewController = VideoPlayerViewController(module: item.module)
videoPlayerViewController.streamUrl = item.streamUrl
videoPlayerViewController.fullUrl = item.fullUrl
videoPlayerViewController.episodeImageUrl = item.imageUrl
videoPlayerViewController.episodeNumber = item.episodeNumber
videoPlayerViewController.mediaTitle = item.mediaTitle
videoPlayerViewController.modalPresentationStyle = .fullScreen
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let rootVC = windowScene.windows.first?.rootViewController {
rootVC.present(videoPlayerViewController, animated: true, completion: nil)
}
}
}) {
VStack(alignment: .leading) {
ZStack {
KFImage(URL(string: item.imageUrl.isEmpty ? "https://raw.githubusercontent.com/cranci1/Sora/refs/heads/main/assets/banner2.png" : item.imageUrl))
.placeholder {
RoundedRectangle(cornerRadius: 10)
.fill(Color.gray.opacity(0.3))
.frame(width: 240, height: 135)
.shimmering()
}
.setProcessor(RoundCornerImageProcessor(cornerRadius: 10))
.resizable()
.aspectRatio(16/9, contentMode: .fill)
.frame(width: 240, height: 135)
.cornerRadius(10)
.clipped()
.overlay(
KFImage(URL(string: item.module.metadata.iconUrl))
.resizable()
.frame(width: 24, height: 24)
.cornerRadius(4)
.padding(4),
alignment: .topLeading
)
}
.overlay(
ZStack {
Rectangle()
.fill(Color.black.opacity(0.3))
.blur(radius: 3)
.frame(height: 30)
ProgressView(value: item.progress)
.progressViewStyle(LinearProgressViewStyle(tint: .white))
.padding(.horizontal, 8)
.scaleEffect(x: 1, y: 1.5, anchor: .center)
},
alignment: .bottom
)
VStack(alignment: .leading) {
Text("Episode \(item.episodeNumber)")
.font(.caption)
.lineLimit(1)
.foregroundColor(.secondary)
Text(item.mediaTitle)
.font(.caption)
.lineLimit(2)
.foregroundColor(.primary)
.multilineTextAlignment(.leading)
}
.padding(.horizontal, 8)
}
.frame(width: 250, height: 190)
}
.contextMenu {
Button(action: { markContinueWatchingItemAsWatched(item: item) }) {
Label("Mark as Watched", systemImage: "checkmark.circle")
}
Button(role: .destructive, action: { removeContinueWatchingItem(item: item) }) {
Label("Remove Item", systemImage: "trash")
}
}
}
}
.padding(.horizontal, 8)
}
.frame(height: 190)
}
}
VStack(alignment: .leading, spacing: 16) {
HStack(alignment: .bottom, spacing: 5) {
Text("Seasonal")
@ -137,118 +249,6 @@ struct HomeView: View {
}
.padding(.horizontal, 8)
}
if !continueWatchingItems.isEmpty {
VStack(alignment: .leading) {
Text("Continue Watching")
.font(.headline)
.padding(.horizontal, 8)
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 8) {
ForEach(Array(continueWatchingItems.reversed())) { item in
Button(action: {
if UserDefaults.standard.string(forKey: "externalPlayer") == "Sora" {
let customMediaPlayer = CustomMediaPlayer(
module: item.module,
urlString: item.streamUrl,
fullUrl: item.fullUrl,
title: item.mediaTitle,
episodeNumber: item.episodeNumber,
onWatchNext: { },
subtitlesURL: item.subtitles,
episodeImageUrl: item.imageUrl
)
let hostingController = UIHostingController(rootView: customMediaPlayer)
hostingController.modalPresentationStyle = .fullScreen
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let rootVC = windowScene.windows.first?.rootViewController {
rootVC.present(hostingController, animated: true, completion: nil)
}
} else {
let videoPlayerViewController = VideoPlayerViewController(module: item.module)
videoPlayerViewController.streamUrl = item.streamUrl
videoPlayerViewController.fullUrl = item.fullUrl
videoPlayerViewController.episodeImageUrl = item.imageUrl
videoPlayerViewController.episodeNumber = item.episodeNumber
videoPlayerViewController.mediaTitle = item.mediaTitle
videoPlayerViewController.modalPresentationStyle = .fullScreen
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let rootVC = windowScene.windows.first?.rootViewController {
rootVC.present(videoPlayerViewController, animated: true, completion: nil)
}
}
}) {
VStack(alignment: .leading) {
ZStack {
KFImage(URL(string: item.imageUrl.isEmpty ? "https://raw.githubusercontent.com/cranci1/Sora/refs/heads/main/assets/banner2.png" : item.imageUrl))
.placeholder {
RoundedRectangle(cornerRadius: 10)
.fill(Color.gray.opacity(0.3))
.frame(width: 240, height: 135)
.shimmering()
}
.setProcessor(RoundCornerImageProcessor(cornerRadius: 10))
.resizable()
.aspectRatio(16/9, contentMode: .fill)
.frame(width: 240, height: 135)
.cornerRadius(10)
.clipped()
.overlay(
KFImage(URL(string: item.module.metadata.iconUrl))
.resizable()
.frame(width: 24, height: 24)
.cornerRadius(4)
.padding(4),
alignment: .topLeading
)
}
.overlay(
ZStack {
Rectangle()
.fill(Color.black.opacity(0.3))
.blur(radius: 3)
.frame(height: 30)
ProgressView(value: item.progress)
.progressViewStyle(LinearProgressViewStyle(tint: .white))
.padding(.horizontal, 8)
.scaleEffect(x: 1, y: 1.5, anchor: .center)
},
alignment: .bottom
)
VStack(alignment: .leading) {
Text("Episode \(item.episodeNumber)")
.font(.caption)
.lineLimit(1)
.foregroundColor(.secondary)
Text(item.mediaTitle)
.font(.caption)
.lineLimit(2)
.foregroundColor(.primary)
.multilineTextAlignment(.leading)
}
.padding(.horizontal, 8)
}
.frame(width: 250, height: 190)
}
.contextMenu {
Button(action: { markContinueWatchingItemAsWatched(item: item) }) {
Label("Mark as Watched", systemImage: "checkmark.circle")
}
Button(role: .destructive, action: { removeContinueWatchingItem(item: item) }) {
Label("Remove Item", systemImage: "trash")
}
}
}
}
.padding(.horizontal, 8)
}
.frame(height: 190)
}
}
}
.padding(.bottom, 16)
}

View file

@ -51,8 +51,8 @@ struct SettingsViewData: View {
)
}
}
.navigationTitle("App Data")
}
.navigationTitle("App Data")
.navigationViewStyle(StackNavigationViewStyle())
}

View file

@ -50,10 +50,10 @@ struct SettingsViewGeneral: View {
}
}
Section(header: Text("Modules")) {
Section(header: Text("Modules"), footer: Text("Note that the modules will be replaced only if there is a different version string inside the JSON file.")) {
Toggle("Refresh Modules on Launch", isOn: $refreshModulesOnLaunch)
}
}
.navigationTitle("General")
}
}
}

View file

@ -14,11 +14,11 @@ struct SettingsViewPlayer: View {
@AppStorage("rememberPlaySpeed") private var isRememberPlaySpeed = false
@AppStorage("holdSpeedPlayer") private var holdSpeedPlayer: Double = 2.0
private let mediaPlayers = ["Default", "Sora", "VLC", "OutPlayer", "Infuse", "nPlayer"]
private let mediaPlayers = ["Default", "VLC", "OutPlayer", "Infuse", "nPlayer", "Sora"]
var body: some View {
Form {
Section(header: Text("Media Player"), footer: Text("Some features are limited to Sora while others are limited to the Default player, such as ForceLandscape and holdSpeed.")) {
Section(header: Text("Media Player"), footer: Text("Some features are limited to Sora while others are limited to the Default player, such as ForceLandscape and holdSpeed. Unfortunately the ForceLandscape doesn't yet working on the Sora Player.")) {
HStack {
Text("Media Player")
Spacer()