mirror of
https://github.com/cranci1/Sora.git
synced 2026-03-11 17:45:37 +00:00
Merge branch 'main' into dev
This commit is contained in:
commit
b95b909b0f
6 changed files with 0 additions and 473 deletions
|
|
@ -14,10 +14,6 @@ struct ContentView: View {
|
|||
.tabItem {
|
||||
Label("Library", systemImage: "books.vertical")
|
||||
}
|
||||
DownloadView()
|
||||
.tabItem {
|
||||
Label("Downloads", systemImage: "arrow.down.app.fill")
|
||||
}
|
||||
SearchView()
|
||||
.tabItem {
|
||||
Label("Search", systemImage: "magnifyingglass")
|
||||
|
|
|
|||
|
|
@ -105,21 +105,9 @@ struct EpisodeCell: View {
|
|||
|
||||
var body: some View {
|
||||
HStack {
|
||||
if isMultiSelectMode {
|
||||
Button(action: {
|
||||
onSelectionChanged?(!isSelected)
|
||||
}) {
|
||||
Image(systemName: isSelected ? "checkmark.circle.fill" : "circle")
|
||||
.foregroundColor(isSelected ? .accentColor : .secondary)
|
||||
.font(.title3)
|
||||
}
|
||||
.buttonStyle(PlainButtonStyle())
|
||||
}
|
||||
|
||||
episodeThumbnail
|
||||
episodeInfo
|
||||
Spacer()
|
||||
downloadStatusView
|
||||
CircularProgressBar(progress: currentProgress)
|
||||
.frame(width: 40, height: 40)
|
||||
}
|
||||
|
|
@ -292,14 +280,6 @@ struct EpisodeCell: View {
|
|||
|
||||
private var contextMenuContent: some View {
|
||||
Group {
|
||||
if case .notDownloaded = downloadStatus {
|
||||
Button(action: {
|
||||
showDownloadConfirmation = true
|
||||
}) {
|
||||
Label("Download Episode", systemImage: "arrow.down.circle")
|
||||
}
|
||||
}
|
||||
|
||||
if progress <= 0.9 {
|
||||
Button(action: markAsWatched) {
|
||||
Label("Mark as Watched", systemImage: "checkmark.circle")
|
||||
|
|
|
|||
|
|
@ -157,14 +157,6 @@ struct MediaInfoView: View {
|
|||
isFetchingEpisode = false
|
||||
showStreamLoadingView = false
|
||||
}
|
||||
.sheet(isPresented: $showRangeInput) {
|
||||
RangeSelectionSheet(
|
||||
totalEpisodes: episodeLinks.count,
|
||||
onSelectionComplete: { startEpisode, endEpisode in
|
||||
selectEpisodeRange(start: startEpisode, end: endEpisode)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
|
|
@ -397,213 +389,13 @@ struct MediaInfoView: View {
|
|||
.fontWeight(.bold)
|
||||
|
||||
Spacer()
|
||||
|
||||
multiSelectControls
|
||||
episodeNavigationSection
|
||||
}
|
||||
|
||||
if isMultiSelectMode && !selectedEpisodes.isEmpty {
|
||||
multiSelectActionBar
|
||||
}
|
||||
|
||||
episodeListSection
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var multiSelectControls: some View {
|
||||
if isMultiSelectMode {
|
||||
if useIconOnlyButtons {
|
||||
HStack(spacing: multiselectButtonSpacing) {
|
||||
Menu {
|
||||
Button(action: {
|
||||
selectedEpisodes.removeAll()
|
||||
}) {
|
||||
Label("Clear All", systemImage: "clear")
|
||||
}
|
||||
|
||||
Button(action: {
|
||||
showRangeInput = true
|
||||
}) {
|
||||
Label("Range Select", systemImage: "list.bullet.rectangle")
|
||||
}
|
||||
} label: {
|
||||
Image(systemName: "ellipsis.circle")
|
||||
.font(.system(size: 18, weight: .medium))
|
||||
.foregroundColor(.primary)
|
||||
.frame(width: 36, height: 36)
|
||||
.background(Color(UIColor.tertiarySystemFill))
|
||||
.clipShape(Circle())
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
Button(action: {
|
||||
selectAllVisibleEpisodes()
|
||||
}) {
|
||||
Image(systemName: "checkmark.circle")
|
||||
.font(.system(size: 18, weight: .medium))
|
||||
.foregroundColor(.primary)
|
||||
.frame(width: 36, height: 36)
|
||||
.background(Color(UIColor.tertiarySystemFill))
|
||||
.clipShape(Circle())
|
||||
}
|
||||
|
||||
Button(action: {
|
||||
isMultiSelectMode = false
|
||||
selectedEpisodes.removeAll()
|
||||
}) {
|
||||
Text("Done")
|
||||
.font(.system(size: 15, weight: .semibold))
|
||||
.foregroundColor(.white)
|
||||
.padding(.horizontal, 16)
|
||||
.padding(.vertical, 8)
|
||||
.background(Color.accentColor)
|
||||
.cornerRadius(18)
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, multiselectPadding)
|
||||
.padding(.vertical, 8)
|
||||
} else {
|
||||
HStack(spacing: multiselectButtonSpacing) {
|
||||
Button(action: {
|
||||
selectedEpisodes.removeAll()
|
||||
}) {
|
||||
HStack(spacing: 6) {
|
||||
Image(systemName: "clear")
|
||||
Text("Clear")
|
||||
}
|
||||
.font(.system(size: 14, weight: .medium))
|
||||
.foregroundColor(.primary)
|
||||
.padding(.horizontal, 12)
|
||||
.padding(.vertical, 8)
|
||||
.background(Color(UIColor.tertiarySystemFill))
|
||||
.cornerRadius(8)
|
||||
}
|
||||
|
||||
Button(action: {
|
||||
showRangeInput = true
|
||||
}) {
|
||||
HStack(spacing: 6) {
|
||||
Image(systemName: "list.bullet.rectangle")
|
||||
Text("Range")
|
||||
}
|
||||
.font(.system(size: 14, weight: .medium))
|
||||
.foregroundColor(.primary)
|
||||
.padding(.horizontal, 12)
|
||||
.padding(.vertical, 8)
|
||||
.background(Color(UIColor.tertiarySystemFill))
|
||||
.cornerRadius(8)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
Button(action: {
|
||||
selectAllVisibleEpisodes()
|
||||
}) {
|
||||
HStack(spacing: 6) {
|
||||
Image(systemName: "checkmark.circle")
|
||||
Text("Select All")
|
||||
}
|
||||
.font(.system(size: 14, weight: .medium))
|
||||
.foregroundColor(.primary)
|
||||
.padding(.horizontal, 12)
|
||||
.padding(.vertical, 8)
|
||||
.background(Color(UIColor.tertiarySystemFill))
|
||||
.cornerRadius(8)
|
||||
}
|
||||
|
||||
Button(action: {
|
||||
isMultiSelectMode = false
|
||||
selectedEpisodes.removeAll()
|
||||
}) {
|
||||
Text("Done")
|
||||
.font(.system(size: 15, weight: .semibold))
|
||||
.foregroundColor(.white)
|
||||
.padding(.horizontal, 16)
|
||||
.padding(.vertical, 8)
|
||||
.background(Color.accentColor)
|
||||
.cornerRadius(8)
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, multiselectPadding)
|
||||
.padding(.vertical, 10)
|
||||
.background(Color(UIColor.secondarySystemBackground).opacity(0.6))
|
||||
.cornerRadius(12)
|
||||
}
|
||||
} else {
|
||||
HStack {
|
||||
Spacer()
|
||||
Button(action: {
|
||||
isMultiSelectMode = true
|
||||
}) {
|
||||
HStack(spacing: 6) {
|
||||
Image(systemName: "checkmark.circle")
|
||||
Text("Select Episodes")
|
||||
}
|
||||
}
|
||||
.font(.system(size: 15, weight: .medium))
|
||||
.foregroundColor(.accentColor)
|
||||
.padding(.horizontal, 16)
|
||||
.padding(.vertical, 10)
|
||||
.background(Color.accentColor.opacity(0.1))
|
||||
.cornerRadius(8)
|
||||
}
|
||||
.padding(.horizontal, 16)
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var multiSelectActionBar: some View {
|
||||
VStack(spacing: 0) {
|
||||
Rectangle()
|
||||
.fill(Color(UIColor.separator))
|
||||
.frame(height: 0.5)
|
||||
|
||||
HStack(spacing: 12) {
|
||||
HStack(spacing: 6) {
|
||||
Image(systemName: "checkmark.circle.fill")
|
||||
.foregroundColor(.accentColor)
|
||||
Text("\(selectedEpisodes.count) selected")
|
||||
.font(.system(size: 15, weight: .medium))
|
||||
.foregroundColor(.primary)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
if isBulkDownloading {
|
||||
HStack(spacing: 8) {
|
||||
ProgressView()
|
||||
.scaleEffect(0.8)
|
||||
Text(bulkDownloadProgress)
|
||||
.font(.system(size: 13))
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
} else {
|
||||
Button(action: {
|
||||
startBulkDownload()
|
||||
}) {
|
||||
HStack(spacing: 6) {
|
||||
Image(systemName: "arrow.down.circle.fill")
|
||||
Text("Download")
|
||||
}
|
||||
.font(.system(size: 15, weight: .semibold))
|
||||
.foregroundColor(.white)
|
||||
.padding(.horizontal, 20)
|
||||
.padding(.vertical, 10)
|
||||
.background(Color.accentColor)
|
||||
.cornerRadius(8)
|
||||
}
|
||||
.disabled(selectedEpisodes.isEmpty)
|
||||
.opacity(selectedEpisodes.isEmpty ? 0.6 : 1.0)
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 16)
|
||||
.padding(.vertical, 12)
|
||||
}
|
||||
.background(Color(UIColor.systemBackground))
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var episodeNavigationSection: some View {
|
||||
Group {
|
||||
|
|
@ -731,8 +523,6 @@ struct MediaInfoView: View {
|
|||
|
||||
userDefaults.synchronize()
|
||||
Logger.shared.log("Marked episodes watched within season \(selectedSeason + 1) of \"\(title)\".", type: "General")
|
||||
} else {
|
||||
// Handle non-season case if needed
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1679,138 +1469,3 @@ struct MediaInfoView: View {
|
|||
}.resume()
|
||||
}
|
||||
}
|
||||
|
||||
struct RangeSelectionSheet: View {
|
||||
let totalEpisodes: Int
|
||||
let onSelectionComplete: (Int, Int) -> Void
|
||||
|
||||
@State private var startEpisode: String = "1"
|
||||
@State private var endEpisode: String = ""
|
||||
@State private var showError: Bool = false
|
||||
@State private var errorMessage: String = ""
|
||||
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
VStack(spacing: 20) {
|
||||
Text("Select Episode Range")
|
||||
.font(.title2)
|
||||
.fontWeight(.bold)
|
||||
.padding(.top)
|
||||
|
||||
VStack(alignment: .leading, spacing: 16) {
|
||||
HStack {
|
||||
Text("From Episode:")
|
||||
.frame(width: 100, alignment: .leading)
|
||||
TextField("1", text: $startEpisode)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
.keyboardType(.numberPad)
|
||||
}
|
||||
|
||||
HStack {
|
||||
Text("To Episode:")
|
||||
.frame(width: 100, alignment: .leading)
|
||||
TextField("\(totalEpisodes)", text: $endEpisode)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
.keyboardType(.numberPad)
|
||||
}
|
||||
}
|
||||
.padding(.horizontal)
|
||||
|
||||
if !startEpisode.isEmpty && !endEpisode.isEmpty {
|
||||
let preview = generatePreviewText()
|
||||
if !preview.isEmpty {
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
Text("Preview:")
|
||||
.font(.headline)
|
||||
Text(preview)
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
.padding()
|
||||
.background(Color(UIColor.secondarySystemBackground))
|
||||
.cornerRadius(8)
|
||||
}
|
||||
.padding(.horizontal)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
HStack(spacing: 16) {
|
||||
Button("Cancel") {
|
||||
dismiss()
|
||||
}
|
||||
.foregroundColor(.secondary)
|
||||
.padding()
|
||||
.frame(maxWidth: .infinity)
|
||||
.background(Color(UIColor.secondarySystemBackground))
|
||||
.cornerRadius(10)
|
||||
|
||||
Button("Select") {
|
||||
validateAndSelect()
|
||||
}
|
||||
.foregroundColor(.white)
|
||||
.padding()
|
||||
.frame(maxWidth: .infinity)
|
||||
.background(Color.accentColor)
|
||||
.cornerRadius(10)
|
||||
.disabled(!isValidRange())
|
||||
}
|
||||
.padding(.horizontal)
|
||||
.padding(.bottom)
|
||||
}
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.navigationBarTitle("Episode Range")
|
||||
.navigationBarItems(trailing: Button("Done") { dismiss() })
|
||||
}
|
||||
.onAppear {
|
||||
endEpisode = "\(totalEpisodes)"
|
||||
}
|
||||
.alert("Invalid Range", isPresented: $showError) {
|
||||
Button("OK") { }
|
||||
} message: {
|
||||
Text(errorMessage)
|
||||
}
|
||||
}
|
||||
|
||||
private func isValidRange() -> Bool {
|
||||
guard let start = Int(startEpisode),
|
||||
let end = Int(endEpisode) else { return false }
|
||||
|
||||
return start >= 1 && end <= totalEpisodes && start <= end
|
||||
}
|
||||
|
||||
private func generatePreviewText() -> String {
|
||||
guard let start = Int(startEpisode),
|
||||
let end = Int(endEpisode),
|
||||
isValidRange() else { return "" }
|
||||
|
||||
let count = end - start + 1
|
||||
return "Will select \(count) episode\(count == 1 ? "" : "s"): Episodes \(start)-\(end)"
|
||||
}
|
||||
|
||||
private func validateAndSelect() {
|
||||
guard let start = Int(startEpisode),
|
||||
let end = Int(endEpisode) else {
|
||||
errorMessage = "Please enter valid episode numbers"
|
||||
showError = true
|
||||
return
|
||||
}
|
||||
|
||||
guard start >= 1 && end <= totalEpisodes else {
|
||||
errorMessage = "Episode numbers must be between 1 and \(totalEpisodes)"
|
||||
showError = true
|
||||
return
|
||||
}
|
||||
|
||||
guard start <= end else {
|
||||
errorMessage = "Start episode must be less than or equal to end episode"
|
||||
showError = true
|
||||
return
|
||||
}
|
||||
|
||||
onSelectionComplete(start, end)
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,94 +0,0 @@
|
|||
//
|
||||
// SettingsViewPerformance.swift
|
||||
// Sora
|
||||
//
|
||||
// Created by Claude on 19/06/24.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct SettingsViewPerformance: View {
|
||||
@ObservedObject private var performanceMonitor = PerformanceMonitor.shared
|
||||
@State private var showResetConfirmation = false
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
Section(header: Text("Performance Monitoring")) {
|
||||
Toggle("Enable Performance Monitoring", isOn: Binding(
|
||||
get: { performanceMonitor.isEnabled },
|
||||
set: { performanceMonitor.setEnabled($0) }
|
||||
))
|
||||
|
||||
Button(action: {
|
||||
showResetConfirmation = true
|
||||
}) {
|
||||
HStack {
|
||||
Text("Reset Metrics")
|
||||
.foregroundColor(.primary)
|
||||
Spacer()
|
||||
Image(systemName: "arrow.clockwise")
|
||||
}
|
||||
}
|
||||
.disabled(!performanceMonitor.isEnabled)
|
||||
|
||||
Button(action: {
|
||||
performanceMonitor.logMetrics()
|
||||
DropManager.shared.showDrop(title: "Metrics Logged", subtitle: "Check logs for details", duration: 1.0, icon: UIImage(systemName: "doc.text"))
|
||||
}) {
|
||||
HStack {
|
||||
Text("Log Current Metrics")
|
||||
.foregroundColor(.primary)
|
||||
Spacer()
|
||||
Image(systemName: "doc.text")
|
||||
}
|
||||
}
|
||||
.disabled(!performanceMonitor.isEnabled)
|
||||
}
|
||||
|
||||
if performanceMonitor.isEnabled {
|
||||
Section(header: Text("About Performance Monitoring"), footer: Text("Performance monitoring helps track app resource usage and identify potential issues with network requests, cache efficiency, and memory management.")) {
|
||||
Text("Performance monitoring helps track app resource usage and identify potential issues with network requests, cache efficiency, and memory management.")
|
||||
.font(.footnote)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("Performance")
|
||||
.alert(isPresented: $showResetConfirmation) {
|
||||
Alert(
|
||||
title: Text("Reset Performance Metrics"),
|
||||
message: Text("Are you sure you want to reset all performance metrics? This action cannot be undone."),
|
||||
primaryButton: .destructive(Text("Reset")) {
|
||||
performanceMonitor.resetMetrics()
|
||||
DropManager.shared.showDrop(title: "Metrics Reset", subtitle: "", duration: 1.0, icon: UIImage(systemName: "arrow.clockwise"))
|
||||
},
|
||||
secondaryButton: .cancel()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct MetricRow: View {
|
||||
let title: String
|
||||
let value: String
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
Text(title)
|
||||
.font(.system(size: 15))
|
||||
.foregroundColor(.secondary)
|
||||
Spacer()
|
||||
Text(value)
|
||||
.font(.system(size: 15, weight: .medium))
|
||||
.foregroundColor(.primary)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SettingsViewPerformance_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
NavigationView {
|
||||
SettingsViewPerformance()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,9 +18,6 @@ struct SettingsView: View {
|
|||
NavigationLink(destination: SettingsViewPlayer()) {
|
||||
Text("Media Player")
|
||||
}
|
||||
NavigationLink(destination: SettingsViewDownloads().environmentObject(JSController.shared)) {
|
||||
Text("Downloads")
|
||||
}
|
||||
NavigationLink(destination: SettingsViewModule()) {
|
||||
Text("Modules")
|
||||
}
|
||||
|
|
@ -36,9 +33,6 @@ struct SettingsView: View {
|
|||
NavigationLink(destination: SettingsViewLogger()) {
|
||||
Text("Logs")
|
||||
}
|
||||
NavigationLink(destination: SettingsViewPerformance()) {
|
||||
Text("Performance")
|
||||
}
|
||||
}
|
||||
|
||||
Section(header: Text("Info")) {
|
||||
|
|
|
|||
|
|
@ -76,7 +76,6 @@
|
|||
722248662DCBC13E00CABE2D /* JSController-Downloads.swift in Sources */ = {isa = PBXBuildFile; fileRef = 722248652DCBC13E00CABE2D /* JSController-Downloads.swift */; };
|
||||
72443C7D2DC8036500A61321 /* DownloadView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72443C7C2DC8036500A61321 /* DownloadView.swift */; };
|
||||
72443C7F2DC8038300A61321 /* SettingsViewDownloads.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72443C7E2DC8038300A61321 /* SettingsViewDownloads.swift */; };
|
||||
7272206E2DD6336100C2A4A2 /* SettingsViewPerformance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7272206D2DD6336100C2A4A2 /* SettingsViewPerformance.swift */; };
|
||||
727220712DD642B100C2A4A2 /* JSController-StreamTypeDownload.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7272206F2DD642B100C2A4A2 /* JSController-StreamTypeDownload.swift */; };
|
||||
727220722DD642B100C2A4A2 /* JSController+MP4Download.swift in Sources */ = {isa = PBXBuildFile; fileRef = 727220702DD642B100C2A4A2 /* JSController+MP4Download.swift */; };
|
||||
72AC3A012DD4DAEB00C60B96 /* ImagePrefetchManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72AC39FE2DD4DAEA00C60B96 /* ImagePrefetchManager.swift */; };
|
||||
|
|
@ -155,7 +154,6 @@
|
|||
722248652DCBC13E00CABE2D /* JSController-Downloads.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSController-Downloads.swift"; sourceTree = "<group>"; };
|
||||
72443C7C2DC8036500A61321 /* DownloadView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadView.swift; sourceTree = "<group>"; };
|
||||
72443C7E2DC8038300A61321 /* SettingsViewDownloads.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewDownloads.swift; sourceTree = "<group>"; };
|
||||
7272206D2DD6336100C2A4A2 /* SettingsViewPerformance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewPerformance.swift; sourceTree = "<group>"; };
|
||||
7272206F2DD642B100C2A4A2 /* JSController-StreamTypeDownload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSController-StreamTypeDownload.swift"; sourceTree = "<group>"; };
|
||||
727220702DD642B100C2A4A2 /* JSController+MP4Download.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSController+MP4Download.swift"; sourceTree = "<group>"; };
|
||||
72AC39FD2DD4DAEA00C60B96 /* EpisodeMetadataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EpisodeMetadataManager.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -278,7 +276,6 @@
|
|||
133D7C832D2BE2630075467E /* SettingsSubViews */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7272206D2DD6336100C2A4A2 /* SettingsViewPerformance.swift */,
|
||||
1E9FF1D22D403E42008AC100 /* SettingsViewLoggerFilter.swift */,
|
||||
1399FAD32D3AB38C00E97C31 /* SettingsViewLogger.swift */,
|
||||
133D7C842D2BE2630075467E /* SettingsViewModule.swift */,
|
||||
|
|
@ -637,7 +634,6 @@
|
|||
13DB468E2D90093A008CBC03 /* Anilist-Token.swift in Sources */,
|
||||
1EAC7A322D888BC50083984D /* MusicProgressSlider.swift in Sources */,
|
||||
722248632DCBAA4700CABE2D /* JSController-HeaderManager.swift in Sources */,
|
||||
7272206E2DD6336100C2A4A2 /* SettingsViewPerformance.swift in Sources */,
|
||||
722248642DCBAA4700CABE2D /* JSController+M3U8Download.swift in Sources */,
|
||||
133D7C942D2BE2640075467E /* JSController.swift in Sources */,
|
||||
133D7C922D2BE2640075467E /* URLSession.swift in Sources */,
|
||||
|
|
|
|||
Loading…
Reference in a new issue