From 2cf0c01ce5433f676c98392d2d883a0311efa56f Mon Sep 17 00:00:00 2001 From: cranci1 <100066266+cranci1@users.noreply.github.com> Date: Sat, 28 Dec 2024 16:53:27 +0100 Subject: [PATCH] homepage --- Sora/Utils/Modules/ModulesManager.swift | 4 +- Sora/Views/HomeView.swift | 129 +++++++++++++++++++++++- 2 files changed, 130 insertions(+), 3 deletions(-) diff --git a/Sora/Utils/Modules/ModulesManager.swift b/Sora/Utils/Modules/ModulesManager.swift index 2539e88..5965b0d 100644 --- a/Sora/Utils/Modules/ModulesManager.swift +++ b/Sora/Utils/Modules/ModulesManager.swift @@ -43,6 +43,7 @@ class ModulesManager: ObservableObject { self.moduleURLs[module.name] = urlString self.saveModuleData() self.saveModuleURLs() + NotificationCenter.default.post(name: .moduleAdded, object: nil) completion(.success(())) } else { completion(.failure(ModuleError.duplicateModule)) @@ -61,6 +62,7 @@ class ModulesManager: ObservableObject { moduleURLs.removeValue(forKey: name) saveModuleData() saveModuleURLs() + NotificationCenter.default.post(name: .moduleRemoved, object: nil) } } @@ -150,4 +152,4 @@ class ModulesManager: ObservableObject { } } } -} +} \ No newline at end of file diff --git a/Sora/Views/HomeView.swift b/Sora/Views/HomeView.swift index 110daa3..1aedaaa 100644 --- a/Sora/Views/HomeView.swift +++ b/Sora/Views/HomeView.swift @@ -6,10 +6,135 @@ // import SwiftUI +import Kingfisher +import SwiftSoup struct HomeView: View { + @StateObject private var modulesManager = ModulesManager() + @State private var featuredItems: [String: [SearchResult]] = [:] + @State private var isLoading = true + var body: some View { - Text("Home View") - .navigationTitle("Home") + NavigationView { + ScrollView { + VStack(alignment: .leading) { + if isLoading { + ProgressView("Loading Featured Items...") + .padding() + } else { + ForEach(modulesManager.modules, id: \.name) { module in + if let items = featuredItems[module.name], !items.isEmpty { + VStack(alignment: .leading) { + HStack(alignment: .bottom) { + Text("Featured") + .font(.title2) + .bold() + .padding(.leading) + + Text("on \(module.name)") + .font(.system(size: 15)) + .foregroundColor(.secondary) + .bold() + } + + ScrollView(.horizontal, showsIndicators: false) { + HStack(spacing: 20) { + ForEach(items) { item in + NavigationLink(destination: AnimeInfoView(module: module, anime: item)) { + VStack { + KFImage(URL(string: item.imageUrl)) + .resizable() + .scaledToFill() + .frame(width: 120, height: 180) + .clipped() + .cornerRadius(8) + + Text(item.name) + .font(.caption) + .lineLimit(1) + .foregroundColor(.primary) + } + .frame(width: 120) + .padding(.leading, 5) + } + } + } + .padding(.horizontal) + } + } + .padding(.bottom) + } + } + } + } + .navigationTitle("Home") + } + .onAppear { + if featuredItems.isEmpty { + fetchFeaturedItems() + } + } + } + .navigationViewStyle(StackNavigationViewStyle()) + } + + private func fetchFeaturedItems() { + isLoading = true + let group = DispatchGroup() + + for module in modulesManager.modules { + group.enter() + fetchFeaturedItems(for: module) { items in + DispatchQueue.main.async { + featuredItems[module.name] = items + group.leave() + } + } + } + + group.notify(queue: .main) { + isLoading = false + } + } + + private func fetchFeaturedItems(for module: ModuleStruct, completion: @escaping ([SearchResult]) -> Void) { + let urlString = module.module[0].featured.url + guard let url = URL(string: urlString) else { + completion([]) + return + } + + URLSession.custom.dataTask(with: url) { data, response, error in + guard let data = data, error == nil else { + completion([]) + return + } + + do { + let html = String(data: data, encoding: .utf8) ?? "" + let document = try SwiftSoup.parse(html) + let elements = try document.select(module.module[0].featured.documentSelector) + + var results: [SearchResult] = [] + for element in elements { + let title = try element.select(module.module[0].featured.title).text() + let href = try element.select(module.module[0].featured.href).attr("href") + var imageURL = try element.select(module.module[0].featured.image.url).attr(module.module[0].featured.image.attribute) + + if !imageURL.starts(with: "http") { + imageURL = "\(module.module[0].details.baseURL)\(imageURL)" + } + + let result = SearchResult(name: title, imageUrl: imageURL, href: href) + results.append(result) + } + + completion(results) + } catch { + print("Error parsing HTML: \(error)") + Logger.shared.log("Error parsing HTML: \(error)") + completion([]) + } + }.resume() } }