added library
Some checks are pending
Build and Release IPA / Build IPA (push) Waiting to run

This commit is contained in:
cranci1 2025-01-12 09:48:26 +01:00
parent 13d666fcf7
commit 74e03d9733
6 changed files with 160 additions and 18 deletions

View file

@ -21,6 +21,7 @@
133D7C932D2BE2640075467E /* Modules.swift in Sources */ = {isa = PBXBuildFile; fileRef = 133D7C892D2BE2640075467E /* Modules.swift */; };
133D7C942D2BE2640075467E /* JSController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 133D7C8B2D2BE2640075467E /* JSController.swift */; };
133D7C972D2BE2AF0075467E /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 133D7C962D2BE2AF0075467E /* Kingfisher */; };
133F55BB2D33B55100E08EEA /* LibraryManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 133F55BA2D33B55100E08EEA /* LibraryManager.swift */; };
138AA1B82D2D66FD0021F9DF /* EpisodeCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 138AA1B62D2D66FD0021F9DF /* EpisodeCell.swift */; };
138AA1B92D2D66FD0021F9DF /* CircularProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 138AA1B72D2D66FD0021F9DF /* CircularProgressBar.swift */; };
13DC0C462D302C7500D0F966 /* VideoPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13DC0C452D302C7500D0F966 /* VideoPlayer.swift */; };
@ -46,6 +47,7 @@
133D7C872D2BE2640075467E /* URLSession.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLSession.swift; sourceTree = "<group>"; };
133D7C892D2BE2640075467E /* Modules.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Modules.swift; sourceTree = "<group>"; };
133D7C8B2D2BE2640075467E /* JSController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSController.swift; sourceTree = "<group>"; };
133F55BA2D33B55100E08EEA /* LibraryManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryManager.swift; sourceTree = "<group>"; };
138AA1B62D2D66FD0021F9DF /* EpisodeCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EpisodeCell.swift; sourceTree = "<group>"; };
138AA1B72D2D66FD0021F9DF /* CircularProgressBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CircularProgressBar.swift; sourceTree = "<group>"; };
13DC0C412D2EC9BA00D0F966 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
@ -111,10 +113,10 @@
133D7C7B2D2BE2630075467E /* Views */ = {
isa = PBXGroup;
children = (
133F55B92D33B53E00E08EEA /* LibraryView */,
133D7C832D2BE2630075467E /* SettingsSubViews */,
133D7C7F2D2BE2630075467E /* MediaInfoView */,
133D7C7D2D2BE2630075467E /* HomeView.swift */,
133D7C7E2D2BE2630075467E /* LibraryView.swift */,
133D7C7C2D2BE2630075467E /* SearchView.swift */,
133D7C822D2BE2630075467E /* SettingsView.swift */,
);
@ -173,6 +175,15 @@
path = Loaders;
sourceTree = "<group>";
};
133F55B92D33B53E00E08EEA /* LibraryView */ = {
isa = PBXGroup;
children = (
133D7C7E2D2BE2630075467E /* LibraryView.swift */,
133F55BA2D33B55100E08EEA /* LibraryManager.swift */,
);
path = LibraryView;
sourceTree = "<group>";
};
138AA1B52D2D66EC0021F9DF /* EpisodeCell */ = {
isa = PBXGroup;
children = (
@ -309,6 +320,7 @@
133D7C942D2BE2640075467E /* JSController.swift in Sources */,
133D7C922D2BE2640075467E /* URLSession.swift in Sources */,
133D7C912D2BE2640075467E /* SettingsViewModule.swift in Sources */,
133F55BB2D33B55100E08EEA /* LibraryManager.swift in Sources */,
133D7C8E2D2BE2640075467E /* LibraryView.swift in Sources */,
133D7C6E2D2BE2500075467E /* SoraApp.swift in Sources */,
138AA1B92D2D66FD0021F9DF /* CircularProgressBar.swift in Sources */,

View file

@ -11,12 +11,14 @@ import SwiftUI
struct SoraApp: App {
@StateObject private var settings = Settings()
@StateObject private var moduleManager = ModuleManager()
@StateObject private var librarykManager = LibraryManager()
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(moduleManager)
.environmentObject(settings)
.environmentObject(librarykManager)
.accentColor(settings.accentColor)
.onAppear {
settings.updateAppearance()

View file

@ -1,16 +0,0 @@
//
// LibraryView.swift
// Sora
//
// Created by Francesco on 05/01/25.
//
import SwiftUI
struct LibraryView: View {
var body: some View {
Text("Library View")
.font(.largeTitle)
.padding()
}
}

View file

@ -0,0 +1,63 @@
//
// LibraryManager.swift
// Sora
//
// Created by Francesco on 12/01/25.
//
import Foundation
import SwiftUI
struct LibraryItem: Codable, Identifiable {
let id: UUID
let title: String
let imageUrl: String
let href: String
let moduleId: String
let dateAdded: Date
init(title: String, imageUrl: String, href: String, moduleId: String) {
self.id = UUID()
self.title = title
self.imageUrl = imageUrl
self.href = href
self.moduleId = moduleId
self.dateAdded = Date()
}
}
class LibraryManager: ObservableObject {
@Published var bookmarks: [LibraryItem] = []
private let bookmarksKey = "bookmarkedItems"
init() {
loadBookmarks()
}
private func loadBookmarks() {
if let data = UserDefaults.standard.data(forKey: bookmarksKey),
let decoded = try? JSONDecoder().decode([LibraryItem].self, from: data) {
bookmarks = decoded
}
}
private func saveBookmarks() {
if let encoded = try? JSONEncoder().encode(bookmarks) {
UserDefaults.standard.set(encoded, forKey: bookmarksKey)
}
}
func isBookmarked(href: String) -> Bool {
bookmarks.contains { $0.href == href }
}
func toggleBookmark(title: String, imageUrl: String, href: String, moduleId: String) {
if let index = bookmarks.firstIndex(where: { $0.href == href }) {
bookmarks.remove(at: index)
} else {
let bookmark = LibraryItem(title: title, imageUrl: imageUrl, href: href, moduleId: moduleId)
bookmarks.insert(bookmark, at: 0)
}
saveBookmarks()
}
}

View file

@ -0,0 +1,73 @@
//
// LibraryView.swift
// Sora
//
// Created by Francesco on 05/01/25.
//
import SwiftUI
import Kingfisher
struct LibraryView: View {
@EnvironmentObject private var libraryManager: LibraryManager
@EnvironmentObject private var moduleManager: ModuleManager
private let columns = [
GridItem(.adaptive(minimum: 150), spacing: 16)
]
var body: some View {
NavigationView {
ScrollView {
if libraryManager.bookmarks.isEmpty {
VStack(spacing: 8) {
Image(systemName: "magazine")
.font(.largeTitle)
.foregroundColor(.secondary)
Text("No Items saved")
.font(.headline)
Text("You can bookmark items to then find them easily here")
.font(.caption)
.foregroundColor(.secondary)
}
.padding()
.frame(maxWidth: .infinity)
} else {
LazyVGrid(columns: columns, spacing: 16) {
ForEach(libraryManager.bookmarks) { item in
if let module = moduleManager.modules.first(where: { $0.id.uuidString == item.moduleId }) {
NavigationLink(destination: MediaInfoView(title: item.title, imageUrl: item.imageUrl, href: item.href, module: module)) {
VStack {
ZStack(alignment: .bottomTrailing) {
KFImage(URL(string: item.imageUrl))
.resizable()
.aspectRatio(2/3, contentMode: .fill)
.cornerRadius(10)
.frame(width: 150, height: 225)
KFImage(URL(string: module.metadata.iconUrl))
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 35, height: 35)
.clipShape(Circle())
.padding(5)
}
Text(item.title)
.font(.subheadline)
.foregroundColor(.primary)
.lineLimit(2)
.multilineTextAlignment(.center)
.padding(.horizontal, 8)
}
}
}
}
}
.padding()
}
}
.navigationTitle("Library")
}
}
}

View file

@ -34,6 +34,7 @@ struct MediaInfoView: View {
@StateObject private var jsController = JSController()
@EnvironmentObject var moduleManager: ModuleManager
@EnvironmentObject private var libraryManager: LibraryManager
var body: some View {
Group {
@ -147,10 +148,17 @@ struct MediaInfoView: View {
}
Button(action: {
libraryManager.toggleBookmark(
title: title,
imageUrl: imageUrl,
href: href,
moduleId: module.id.uuidString
)
}) {
Image(systemName: "bookmark")
Image(systemName: libraryManager.isBookmarked(href: href) ? "bookmark.fill" : "bookmark")
.resizable()
.frame(width: 20, height: 27)
.foregroundColor(Color.accentColor)
}
}