Skip to content

Commit 5e4838d

Browse files
authored
Add AniList tracking for downloaded episodes + Add auto skip filler episodes option (#266)
1 parent 05914cc commit 5e4838d

File tree

9 files changed

+76
-29
lines changed

9 files changed

+76
-29
lines changed

Sora/Utlis & Misc/DownloadUtils/DownloadModels.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,8 @@ struct AssetMetadata: Codable {
415415
let seasonNumber: Int?
416416
/// Indicates whether this episode is a filler (derived from metadata at download time)
417417
let isFiller: Bool?
418+
let aniListID: Int?
419+
let totalEpisodes: Int?
418420

419421
init(
420422
title: String,
@@ -428,7 +430,9 @@ struct AssetMetadata: Codable {
428430
showPosterURL: URL? = nil,
429431
episodeTitle: String? = nil,
430432
seasonNumber: Int? = nil,
431-
isFiller: Bool? = nil
433+
isFiller: Bool? = nil,
434+
aniListID: Int? = nil,
435+
totalEpisodes: Int? = nil
432436
) {
433437
self.title = title
434438
self.overview = overview
@@ -442,6 +446,8 @@ struct AssetMetadata: Codable {
442446
self.episodeTitle = episodeTitle
443447
self.seasonNumber = seasonNumber
444448
self.isFiller = isFiller
449+
self.aniListID = aniListID
450+
self.totalEpisodes = totalEpisodes
445451
}
446452
}
447453

Sora/Utlis & Misc/JSLoader/Downloads/JSController+Downloader.swift

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,11 @@ struct DownloadRequest {
2323
let aniListID: Int?
2424
let malID: Int?
2525
let isFiller: Bool?
26+
let totalEpisodes: Int?
2627

2728
init(url: URL, headers: [String: String], title: String? = nil, imageURL: URL? = nil,
2829
isEpisode: Bool = false, showTitle: String? = nil, season: Int? = nil,
29-
episode: Int? = nil, subtitleURL: URL? = nil, showPosterURL: URL? = nil, aniListID: Int? = nil, malID: Int? = nil, isFiller: Bool? = nil) {
30+
episode: Int? = nil, subtitleURL: URL? = nil, showPosterURL: URL? = nil, aniListID: Int? = nil, malID: Int? = nil, isFiller: Bool? = nil, totalEpisodes: Int? = nil) {
3031
self.url = url
3132
self.headers = headers
3233
self.title = title
@@ -40,6 +41,7 @@ struct DownloadRequest {
4041
self.aniListID = aniListID
4142
self.malID = malID
4243
self.isFiller = isFiller
44+
self.totalEpisodes = totalEpisodes
4345
}
4446
}
4547

@@ -62,14 +64,15 @@ extension JSController {
6264
showTitle: String? = nil, season: Int? = nil, episode: Int? = nil,
6365
subtitleURL: URL? = nil, showPosterURL: URL? = nil,
6466
aniListID: Int? = nil, malID: Int? = nil, isFiller: Bool? = nil,
67+
totalEpisodes: Int? = nil,
6568
completionHandler: ((Bool, String) -> Void)? = nil) {
6669

6770

6871
let request = DownloadRequest(
6972
url: url, headers: headers, title: title, imageURL: imageURL,
7073
isEpisode: isEpisode, showTitle: showTitle, season: season,
7174
episode: episode, subtitleURL: subtitleURL, showPosterURL: showPosterURL,
72-
aniListID: aniListID, malID: malID, isFiller: isFiller
75+
aniListID: aniListID, malID: malID, isFiller: isFiller, totalEpisodes: totalEpisodes
7376
)
7477

7578
logDownloadStart(request: request)
@@ -114,7 +117,8 @@ extension JSController {
114117
showPosterURL: request.showPosterURL,
115118
aniListID: request.aniListID,
116119
malID: request.malID,
117-
isFiller: request.isFiller
120+
isFiller: request.isFiller,
121+
totalEpisodes: request.totalEpisodes
118122
)
119123
self.downloadWithOriginalMethod(request: qualityRequest, completionHandler: completionHandler)
120124
} else {
@@ -142,14 +146,15 @@ extension JSController {
142146
imageURL: URL? = nil, isEpisode: Bool = false, showTitle: String? = nil,
143147
season: Int? = nil, episode: Int? = nil, subtitleURL: URL? = nil,
144148
showPosterURL: URL? = nil, aniListID: Int? = nil, malID: Int? = nil, isFiller: Bool? = nil,
149+
totalEpisodes: Int? = nil,
145150
completionHandler: ((Bool, String) -> Void)? = nil) {
146151

147152

148153
let request = DownloadRequest(
149154
url: url, headers: headers, title: title, imageURL: imageURL,
150155
isEpisode: isEpisode, showTitle: showTitle, season: season,
151156
episode: episode, subtitleURL: subtitleURL, showPosterURL: showPosterURL,
152-
aniListID: aniListID, malID: malID, isFiller: isFiller
157+
aniListID: aniListID, malID: malID, isFiller: isFiller, totalEpisodes: totalEpisodes
153158
)
154159

155160
downloadMP4(request: request, completionHandler: completionHandler)
@@ -382,7 +387,9 @@ extension JSController {
382387
showPosterURL: request.showPosterURL ?? request.imageURL,
383388
episodeTitle: nil,
384389
seasonNumber: nil,
385-
isFiller: request.isFiller
390+
isFiller: request.isFiller,
391+
aniListID: request.aniListID,
392+
totalEpisodes: request.totalEpisodes
386393
)
387394
}
388395

@@ -436,6 +443,7 @@ extension JSController {
436443
aniListID: request.aniListID,
437444
malID: request.malID,
438445
isFiller: request.isFiller,
446+
totalEpisodes: request.totalEpisodes,
439447
completionHandler: completionHandler
440448
)
441449
}

Sora/Utlis & Misc/JSLoader/Downloads/JSController-Downloads.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ extension JSController {
117117
aniListID: Int? = nil,
118118
malID: Int? = nil,
119119
isFiller: Bool? = nil,
120+
totalEpisodes: Int? = nil,
120121
completionHandler: ((Bool, String) -> Void)? = nil
121122
) {
122123
// If a module is provided, use the stream type aware download
@@ -137,6 +138,7 @@ extension JSController {
137138
aniListID: aniListID,
138139
malID: malID,
139140
isFiller: isFiller,
141+
totalEpisodes: totalEpisodes,
140142
completionHandler: completionHandler
141143
)
142144
return
@@ -163,7 +165,9 @@ extension JSController {
163165
season: season,
164166
episode: episode,
165167
showPosterURL: showPosterURL, // Main show poster
166-
isFiller: isFiller
168+
isFiller: isFiller,
169+
aniListID: aniListID,
170+
totalEpisodes: totalEpisodes
167171
)
168172

169173
// Create the download ID now so we can use it for notifications

Sora/Utlis & Misc/JSLoader/Downloads/JSController-StreamTypeDownload.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ extension JSController {
3939
aniListID: Int? = nil,
4040
malID: Int? = nil,
4141
isFiller: Bool? = nil,
42+
totalEpisodes: Int? = nil,
4243
completionHandler: ((Bool, String) -> Void)? = nil
4344
) {
4445
let streamType = module.metadata.streamType.lowercased()
@@ -59,6 +60,7 @@ extension JSController {
5960
aniListID: aniListID,
6061
malID: malID,
6162
isFiller: isFiller,
63+
totalEpisodes: totalEpisodes,
6264
completionHandler: completionHandler
6365
)
6466
}else {
@@ -77,6 +79,7 @@ extension JSController {
7779
aniListID: aniListID,
7880
malID: malID,
7981
isFiller: isFiller,
82+
totalEpisodes: totalEpisodes,
8083
completionHandler: completionHandler
8184
)
8285
}

Sora/Views/DownloadView.swift

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -281,8 +281,8 @@ struct DownloadView: View {
281281
}
282282
},
283283
subtitlesURL: asset.localSubtitleURL?.absoluteString,
284-
aniListID: 0,
285-
totalEpisodes: asset.metadata?.episode ?? 0,
284+
aniListID: asset.metadata?.aniListID ?? 0,
285+
totalEpisodes: asset.metadata?.totalEpisodes ?? 0,
286286
episodeImageUrl: asset.metadata?.posterURL?.absoluteString ?? "",
287287
headers: nil
288288
)
@@ -1050,7 +1050,6 @@ struct EnhancedShowEpisodesView: View {
10501050

10511051
var body: some View {
10521052
ZStack {
1053-
heroImageSection
10541053
mainScrollView
10551054
.navigationBarHidden(true)
10561055
.ignoresSafeArea(.container, edges: .top)
@@ -1099,7 +1098,10 @@ struct EnhancedShowEpisodesView: View {
10991098
@ViewBuilder
11001099
private var mainScrollView: some View {
11011100
ScrollView(showsIndicators: false) {
1102-
contentContainer
1101+
ZStack(alignment: .top) {
1102+
heroImageSection
1103+
contentContainer
1104+
}
11031105
}
11041106
.onAppear {
11051107
UIScrollView.appearance().bounces = false
@@ -1108,24 +1110,22 @@ struct EnhancedShowEpisodesView: View {
11081110

11091111
@ViewBuilder
11101112
private var heroImageSection: some View {
1111-
if let posterURL = group.posterURL {
1112-
LazyImage(url: posterURL) { state in
1113-
if let uiImage = state.imageContainer?.image {
1114-
Image(uiImage: uiImage)
1115-
.resizable()
1116-
.aspectRatio(contentMode: .fill)
1117-
} else {
1118-
placeholderGradient
1113+
Group {
1114+
if let posterURL = group.posterURL {
1115+
LazyImage(url: posterURL) { @MainActor state in
1116+
if let uiImage = state.imageContainer?.image {
1117+
Image(uiImage: uiImage)
1118+
.resizable()
1119+
.aspectRatio(contentMode: .fill)
1120+
.frame(width: UIScreen.main.bounds.width, height: 700)
1121+
.clipped()
1122+
} else {
1123+
placeholderGradient
1124+
}
11191125
}
1126+
} else {
1127+
placeholderGradient
11201128
}
1121-
.ignoresSafeArea(.all)
1122-
.frame(maxWidth: .infinity, maxHeight: 400)
1123-
.clipped()
1124-
} else {
1125-
placeholderGradient
1126-
.ignoresSafeArea(.all)
1127-
.frame(maxWidth: .infinity, maxHeight: 400)
1128-
.clipped()
11291129
}
11301130
}
11311131

@@ -1142,6 +1142,8 @@ struct EnhancedShowEpisodesView: View {
11421142
endPoint: .bottomTrailing
11431143
)
11441144
)
1145+
.frame(width: UIScreen.main.bounds.width, height: 700)
1146+
.clipped()
11451147
}
11461148

11471149
@ViewBuilder

Sora/Views/MediaInfoView/EpisodeCell/EpisodeCell.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -747,7 +747,8 @@ private extension EpisodeCell {
747747
showPosterURL: showPosterImageURL,
748748
aniListID: itemID,
749749
malID: malIDFromParent,
750-
isFiller: isFiller
750+
isFiller: isFiller,
751+
totalEpisodes: totalEpisodes
751752
) { success, message in
752753
if success {
753754
Logger.shared.log("Started download for Episode \(self.episodeID + 1): \(self.episode)", type: "Download")

Sora/Views/MediaInfoView/MediaInfoView.swift

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1373,7 +1373,21 @@ struct MediaInfoView: View {
13731373
return
13741374
}
13751375

1376-
let nextEpisode = episodeLinks[currentIndex + 1]
1376+
let autoSkipFillers = UserDefaults.standard.bool(forKey: "autoSkipFillers")
1377+
var nextIndex = currentIndex + 1
1378+
1379+
if autoSkipFillers, let fillerSet = jikanFillerSet {
1380+
while nextIndex < episodeLinks.count, fillerSet.contains(episodeLinks[nextIndex].number) {
1381+
Logger.shared.log("Skipping filler episode \(episodeLinks[nextIndex].number)", type: "Debug")
1382+
nextIndex += 1
1383+
}
1384+
guard nextIndex < episodeLinks.count else {
1385+
Logger.shared.log("No more non-filler episodes to play", type: "Info")
1386+
return
1387+
}
1388+
}
1389+
1390+
let nextEpisode = episodeLinks[nextIndex]
13771391
selectedEpisodeNumber = nextEpisode.number
13781392
fetchStream(href: nextEpisode.href)
13791393
DropManager.shared.showDrop(

Sora/Views/SettingsView/SettingsSubViews/SettingsViewBackup.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ struct SettingsViewBackup: View {
302302
"skipIntroOutroVisible",
303303
"pipButtonVisible",
304304
"autoplayNext",
305+
"autoSkipFillers",
305306
"videoQualityWiFi",
306307
"videoQualityCellular",
307308
"subtitlesEnabled",

Sora/Views/SettingsView/SettingsSubViews/SettingsViewPlayer.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ struct SettingsViewPlayer: View {
258258
@AppStorage("doubleTapSeekEnabled") private var doubleTapSeekEnabled: Bool = false
259259
@AppStorage("skipIntroOutroVisible") private var skipIntroOutroVisible: Bool = true
260260
@AppStorage("autoplayNext") private var autoplayNext: Bool = true
261+
@AppStorage("autoSkipFillers") private var autoSkipFillers: Bool = false
261262
@AppStorage("introDBEnabled") private var introDBEnabled: Bool = true
262263

263264
@AppStorage("videoQualityWiFi") private var wifiQuality: String = VideoQualityPreference.defaultWiFiPreference.rawValue
@@ -301,6 +302,13 @@ struct SettingsViewPlayer: View {
301302
showDivider: true
302303
)
303304

305+
SettingsToggleRow(
306+
icon: "forward.fill",
307+
title: NSLocalizedString("Auto Skip Filler Episodes", comment: ""),
308+
isOn: $autoSkipFillers,
309+
showDivider: true
310+
)
311+
304312
SettingsTextFieldRow(
305313
icon: "timer",
306314
title: NSLocalizedString("Completion Percentage", comment: ""),

0 commit comments

Comments
 (0)