mirror of
https://github.com/cranci1/Sora.git
synced 2026-03-11 17:45:37 +00:00
bookmark logic (#43)
Some checks are pending
Build and Release IPA / Build IPA (push) Waiting to run
Some checks are pending
Build and Release IPA / Build IPA (push) Waiting to run
This commit is contained in:
commit
23ff8a9ba5
6 changed files with 96 additions and 21 deletions
|
|
@ -207,12 +207,24 @@ class CustomMediaPlayerViewController: UIViewController {
|
|||
blackCoverView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
|
||||
])
|
||||
|
||||
backwardButton = UIImageView(image: UIImage(systemName: "gobackward.10"))
|
||||
backwardButton = UIImageView(image: UIImage(systemName: "gobackward"))
|
||||
backwardButton.tintColor = .white
|
||||
backwardButton.contentMode = .scaleAspectFit
|
||||
backwardButton.isUserInteractionEnabled = true
|
||||
|
||||
// 1) Tap gesture → normal skip
|
||||
let backwardTap = UITapGestureRecognizer(target: self, action: #selector(seekBackward))
|
||||
backwardTap.numberOfTapsRequired = 1
|
||||
backwardButton.addGestureRecognizer(backwardTap)
|
||||
|
||||
// 2) Long-press gesture → hold skip
|
||||
let backwardLongPress = UILongPressGestureRecognizer(target: self, action: #selector(seekBackwardLongPress(_:)))
|
||||
backwardLongPress.minimumPressDuration = 0.5 // Adjust as needed
|
||||
backwardButton.addGestureRecognizer(backwardLongPress)
|
||||
|
||||
// Make sure the tap doesn’t fire if the long-press is recognized
|
||||
backwardTap.require(toFail: backwardLongPress)
|
||||
|
||||
controlsContainerView.addSubview(backwardButton)
|
||||
backwardButton.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
|
|
@ -225,14 +237,23 @@ class CustomMediaPlayerViewController: UIViewController {
|
|||
controlsContainerView.addSubview(playPauseButton)
|
||||
playPauseButton.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
forwardButton = UIImageView(image: UIImage(systemName: "goforward.10"))
|
||||
forwardButton.tintColor = .white
|
||||
forwardButton.contentMode = .scaleAspectFit
|
||||
forwardButton.isUserInteractionEnabled = true
|
||||
let forwardTap = UITapGestureRecognizer(target: self, action: #selector(seekForward))
|
||||
forwardButton.addGestureRecognizer(forwardTap)
|
||||
controlsContainerView.addSubview(forwardButton)
|
||||
forwardButton.translatesAutoresizingMaskIntoConstraints = false
|
||||
forwardButton = UIImageView(image: UIImage(systemName: "goforward"))
|
||||
forwardButton.tintColor = .white
|
||||
forwardButton.contentMode = .scaleAspectFit
|
||||
forwardButton.isUserInteractionEnabled = true
|
||||
|
||||
let forwardTap = UITapGestureRecognizer(target: self, action: #selector(seekForward))
|
||||
forwardTap.numberOfTapsRequired = 1
|
||||
forwardButton.addGestureRecognizer(forwardTap)
|
||||
|
||||
let forwardLongPress = UILongPressGestureRecognizer(target: self, action: #selector(seekForwardLongPress(_:)))
|
||||
forwardLongPress.minimumPressDuration = 0.5
|
||||
forwardButton.addGestureRecognizer(forwardLongPress)
|
||||
|
||||
forwardTap.require(toFail: forwardLongPress)
|
||||
|
||||
controlsContainerView.addSubview(forwardButton)
|
||||
forwardButton.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
let sliderView = MusicProgressSlider(
|
||||
value: Binding(get: { self.sliderViewModel.sliderValue },
|
||||
|
|
@ -538,13 +559,36 @@ class CustomMediaPlayerViewController: UIViewController {
|
|||
}
|
||||
}
|
||||
|
||||
@objc func seekBackward() {
|
||||
currentTimeVal = max(currentTimeVal - 10, 0)
|
||||
player.seek(to: CMTime(seconds: currentTimeVal, preferredTimescale: 600))
|
||||
@objc func seekBackwardLongPress(_ gesture: UILongPressGestureRecognizer) {
|
||||
// Only do the skip when the gesture first begins
|
||||
if gesture.state == .began {
|
||||
let holdValue = UserDefaults.standard.double(forKey: "skipIncrementHold")
|
||||
let finalSkip = holdValue > 0 ? holdValue : 30 // fallback to 30 if not set
|
||||
currentTimeVal = max(currentTimeVal - finalSkip, 0)
|
||||
player.seek(to: CMTime(seconds: currentTimeVal, preferredTimescale: 600))
|
||||
}
|
||||
}
|
||||
|
||||
@objc func seekForwardLongPress(_ gesture: UILongPressGestureRecognizer) {
|
||||
if gesture.state == .began {
|
||||
let holdValue = UserDefaults.standard.double(forKey: "skipIncrementHold")
|
||||
let finalSkip = holdValue > 0 ? holdValue : 30
|
||||
currentTimeVal = min(currentTimeVal + finalSkip, duration)
|
||||
player.seek(to: CMTime(seconds: currentTimeVal, preferredTimescale: 600))
|
||||
}
|
||||
}
|
||||
|
||||
@objc func seekBackward() {
|
||||
let skipValue = UserDefaults.standard.double(forKey: "skipIncrement")
|
||||
let finalSkip = skipValue > 0 ? skipValue : 10
|
||||
currentTimeVal = max(currentTimeVal - finalSkip, 0)
|
||||
player.seek(to: CMTime(seconds: currentTimeVal, preferredTimescale: 600))
|
||||
}
|
||||
|
||||
@objc func seekForward() {
|
||||
currentTimeVal = min(currentTimeVal + 10, duration)
|
||||
let skipValue = UserDefaults.standard.double(forKey: "skipIncrement")
|
||||
let finalSkip = skipValue > 0 ? skipValue : 10
|
||||
currentTimeVal = min(currentTimeVal + finalSkip, duration)
|
||||
player.seek(to: CMTime(seconds: currentTimeVal, preferredTimescale: 600))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,14 @@ class LibraryManager: ObservableObject {
|
|||
loadBookmarks()
|
||||
}
|
||||
|
||||
func removeBookmark(item: LibraryItem) {
|
||||
if let index = bookmarks.firstIndex(where: { $0.id == item.id }) {
|
||||
bookmarks.remove(at: index)
|
||||
Logger.shared.log("Removed series \(item.id) from bookmarks.",type: "Debug")
|
||||
saveBookmarks()
|
||||
}
|
||||
}
|
||||
|
||||
private func loadBookmarks() {
|
||||
guard let data = UserDefaults.standard.data(forKey: bookmarksKey) else {
|
||||
Logger.shared.log("No bookmarks data found in UserDefaults.", type: "Error")
|
||||
|
|
|
|||
|
|
@ -114,6 +114,13 @@ struct LibraryView: View {
|
|||
.multilineTextAlignment(.leading)
|
||||
}
|
||||
}
|
||||
.contextMenu {
|
||||
Button(role: .destructive, action: {
|
||||
libraryManager.removeBookmark(item: item)
|
||||
}) {
|
||||
Label("Remove from Bookmarks", systemImage: "trash")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -179,7 +186,7 @@ struct ContinueWatchingSection: View {
|
|||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
HStack(spacing: 8) {
|
||||
ForEach(Array(items.reversed())) { item in
|
||||
ContinueWatchingCell(item: item,markAsWatched: {
|
||||
ContinueWatchingCell(item: item, markAsWatched: {
|
||||
markAsWatched(item)
|
||||
}, removeItem: {
|
||||
removeItem(item)
|
||||
|
|
|
|||
|
|
@ -237,7 +237,7 @@ struct MediaInfoView: View {
|
|||
UserDefaults.standard.set(99999999.0, forKey: "totalTime_\(href)")
|
||||
}
|
||||
refreshTrigger.toggle()
|
||||
Logger.shared.log("Marked \(ep.number) episodes watched within anime \"\(title)\".", type: "General")
|
||||
Logger.shared.log("Marked \(ep.number - 1) episodes watched within anime \"\(title)\".", type: "General")
|
||||
}
|
||||
)
|
||||
.id(refreshTrigger)
|
||||
|
|
|
|||
|
|
@ -13,12 +13,14 @@ struct SettingsViewPlayer: View {
|
|||
@AppStorage("hideNextButton") private var isHideNextButton = false
|
||||
@AppStorage("rememberPlaySpeed") private var isRememberPlaySpeed = false
|
||||
@AppStorage("holdSpeedPlayer") private var holdSpeedPlayer: Double = 2.0
|
||||
@AppStorage("skipIncrement") private var skipIncrement: Double = 10.0
|
||||
@AppStorage("skipIncrementHold") private var skipIncrementHold: Double = 30.0
|
||||
|
||||
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 the Sora and Default player, such as ForceLandscape and holdSpeed")) {
|
||||
Section(header: Text("Media Player"), footer: Text("Some features are limited to the Sora and Default player, such as ForceLandscape, holdSpeed and custom time skip increments.")) {
|
||||
HStack {
|
||||
Text("Media Player")
|
||||
Spacer()
|
||||
|
|
@ -56,7 +58,21 @@ struct SettingsViewPlayer: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Section(header: Text("Skip Settings")) {
|
||||
// Normal skip
|
||||
HStack {
|
||||
Text("Tap Skip:")
|
||||
Spacer()
|
||||
Stepper("\(Int(skipIncrement))s", value: $skipIncrement, in: 5...300, step: 5)
|
||||
}
|
||||
|
||||
// Long-press skip
|
||||
HStack {
|
||||
Text("Long press Skip:")
|
||||
Spacer()
|
||||
Stepper("\(Int(skipIncrementHold))s", value: $skipIncrementHold, in: 5...300, step: 5)
|
||||
}
|
||||
}
|
||||
SubtitleSettingsSection()
|
||||
}
|
||||
.navigationTitle("Player")
|
||||
|
|
|
|||
|
|
@ -58,9 +58,9 @@
|
|||
13DC0C462D302C7500D0F966 /* VideoPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13DC0C452D302C7500D0F966 /* VideoPlayer.swift */; };
|
||||
13EA2BD52D32D97400C1EBD7 /* CustomPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13EA2BD12D32D97400C1EBD7 /* CustomPlayer.swift */; };
|
||||
13EA2BD62D32D97400C1EBD7 /* Double+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13EA2BD32D32D97400C1EBD7 /* Double+Extension.swift */; };
|
||||
13EA2BD72D32D97400C1EBD7 /* MusicProgressSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13EA2BD42D32D97400C1EBD7 /* MusicProgressSlider.swift */; };
|
||||
13EA2BD92D32D98400C1EBD7 /* NormalPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13EA2BD82D32D98400C1EBD7 /* NormalPlayer.swift */; };
|
||||
1E9FF1D32D403E49008AC100 /* SettingsViewLoggerFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E9FF1D22D403E42008AC100 /* SettingsViewLoggerFilter.swift */; };
|
||||
1EAC7A322D888BC50083984D /* MusicProgressSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EAC7A312D888BC50083984D /* MusicProgressSlider.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
|
|
@ -115,9 +115,9 @@
|
|||
13DC0C452D302C7500D0F966 /* VideoPlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayer.swift; sourceTree = "<group>"; };
|
||||
13EA2BD12D32D97400C1EBD7 /* CustomPlayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomPlayer.swift; sourceTree = "<group>"; };
|
||||
13EA2BD32D32D97400C1EBD7 /* Double+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Double+Extension.swift"; sourceTree = "<group>"; };
|
||||
13EA2BD42D32D97400C1EBD7 /* MusicProgressSlider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MusicProgressSlider.swift; sourceTree = "<group>"; };
|
||||
13EA2BD82D32D98400C1EBD7 /* NormalPlayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NormalPlayer.swift; sourceTree = "<group>"; };
|
||||
1E9FF1D22D403E42008AC100 /* SettingsViewLoggerFilter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewLoggerFilter.swift; sourceTree = "<group>"; };
|
||||
1EAC7A312D888BC50083984D /* MusicProgressSlider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MusicProgressSlider.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
|
@ -437,7 +437,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
13EA2BD32D32D97400C1EBD7 /* Double+Extension.swift */,
|
||||
13EA2BD42D32D97400C1EBD7 /* MusicProgressSlider.swift */,
|
||||
1EAC7A312D888BC50083984D /* MusicProgressSlider.swift */,
|
||||
);
|
||||
path = Components;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -532,7 +532,6 @@
|
|||
1334FF4F2D786C9E007E289F /* TMDB-Trending.swift in Sources */,
|
||||
13CBEFDA2D5F7D1200D011EE /* String.swift in Sources */,
|
||||
130C6BFA2D53AB1F00DC1432 /* SettingsViewData.swift in Sources */,
|
||||
13EA2BD72D32D97400C1EBD7 /* MusicProgressSlider.swift in Sources */,
|
||||
1334FF542D787217007E289F /* TMDBRequest.swift in Sources */,
|
||||
1E9FF1D32D403E49008AC100 /* SettingsViewLoggerFilter.swift in Sources */,
|
||||
13EA2BD92D32D98400C1EBD7 /* NormalPlayer.swift in Sources */,
|
||||
|
|
@ -556,6 +555,7 @@
|
|||
1327FBA92D758DEA00FC6689 /* UIDevice+Model.swift in Sources */,
|
||||
138AA1B82D2D66FD0021F9DF /* EpisodeCell.swift in Sources */,
|
||||
133D7C8C2D2BE2640075467E /* SearchView.swift in Sources */,
|
||||
1EAC7A322D888BC50083984D /* MusicProgressSlider.swift in Sources */,
|
||||
133D7C942D2BE2640075467E /* JSController.swift in Sources */,
|
||||
133D7C922D2BE2640075467E /* URLSession.swift in Sources */,
|
||||
133D7C912D2BE2640075467E /* SettingsViewModule.swift in Sources */,
|
||||
|
|
|
|||
Loading…
Reference in a new issue