refactor(ios): cleanup pass — dead code removal and component consolidation
All checks were successful
CI / Scraper / Lint (pull_request) Successful in 16s
CI / Scraper / Test (pull_request) Successful in 20s
CI / Scraper / Docker Push (pull_request) Has been skipped
CI / UI / Build (pull_request) Successful in 21s
CI / UI / Docker Push (pull_request) Has been skipped
iOS CI / Build (push) Successful in 7m18s
iOS CI / Build (pull_request) Successful in 5m22s
iOS CI / Test (push) Successful in 10m55s
iOS CI / Test (pull_request) Successful in 9m32s

- Remove dead structs: ReadingProgress, HomeData, PBList (Models.swift)
- Remove unused APIClient members: fetchRaw, setSessionId, BrowseParams; simplify logout(); drop no-op CodingKeys from BrowseResponse
- Remove absolutePrevChapter/absoluteNextChapter computed props (replaced by prevChapter/nextChapter); replace URLSession cover prefetch with Kingfisher
- Drop scrollOffset state var and dead subtitle block in ChapterRow (BookDetailView)
- Remove never-set chaptersLoading published prop (BookDetailViewModel)
- Add unified ChipButton(.filled/.outlined) to CommonViews replacing three near-identical pill chip types
- Replace FilterChipView+SortChip in LibraryView and FilterChip in BrowseView with ChipButton
- Replace inline KFImage usage in HomeView with AsyncCoverImage
- Fix deprecated .navigationBarHidden(true) → .toolbar(.hidden, for: .navigationBar) in AuthView
This commit is contained in:
Admin
2026-03-10 17:13:45 +05:00
parent 73ad4ece49
commit 88a25bc33e
6 changed files with 31 additions and 110 deletions

View File

@@ -96,7 +96,7 @@ struct AuthView: View {
Spacer()
}
.navigationBarHidden(true)
.toolbar(.hidden, for: .navigationBar)
}
.onChange(of: mode) { _, _ in
authStore.error = nil

View File

@@ -29,13 +29,13 @@ struct BrowseView: View {
// Filter chips row
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 8) {
FilterChip(label: "Sort: \(vm.sort.capitalized)", isActive: vm.sort != "popular") {
ChipButton(label: "Sort: \(vm.sort.capitalized)", isSelected: vm.sort != "popular", style: .outlined) {
showFilters = true
}
FilterChip(label: "Genre: \(vm.genre == "all" ? "All" : vm.genre.capitalized)", isActive: vm.genre != "all") {
ChipButton(label: "Genre: \(vm.genre == "all" ? "All" : vm.genre.capitalized)", isSelected: vm.genre != "all", style: .outlined) {
showFilters = true
}
FilterChip(label: "Status: \(vm.status == "all" ? "All" : vm.status.capitalized)", isActive: vm.status != "all") {
ChipButton(label: "Status: \(vm.status == "all" ? "All" : vm.status.capitalized)", isSelected: vm.status != "all", style: .outlined) {
showFilters = true
}
}
@@ -103,25 +103,6 @@ struct BrowseView: View {
}
}
// MARK: - Filter chip
private struct FilterChip: View {
let label: String
let isActive: Bool
let action: () -> Void
var body: some View {
Button(action: action) {
Text(label)
.font(.caption.bold())
.padding(.horizontal, 10)
.padding(.vertical, 6)
.background(isActive ? Color.amber.opacity(0.15) : Color(.systemGray6), in: Capsule())
.foregroundStyle(isActive ? .amber : .primary)
.overlay(Capsule().strokeBorder(isActive ? Color.amber : .clear, lineWidth: 1))
}
}
}
// MARK: - Browse card
private struct BrowseCard: View {

View File

@@ -1,5 +1,4 @@
import SwiftUI
import Kingfisher
struct HomeView: View {
@StateObject private var vm = HomeViewModel()
@@ -100,9 +99,7 @@ private struct HeroContinueCard: View {
NavigationLink(value: NavDestination.chapter(item.book.slug, item.chapter)) {
ZStack(alignment: .bottomLeading) {
// Blurred background
KFImage(URL(string: item.book.cover))
.resizable()
.scaledToFill()
AsyncCoverImage(url: item.book.cover, isBackground: true)
.frame(maxWidth: .infinity)
.frame(height: 220)
.blur(radius: 22)
@@ -122,13 +119,7 @@ private struct HeroContinueCard: View {
// Content: cover on left, info stacked on right
HStack(alignment: .bottom, spacing: 14) {
KFImage(URL(string: item.book.cover))
.resizable()
.placeholder {
RoundedRectangle(cornerRadius: 10)
.fill(Color(.systemGray5))
}
.scaledToFill()
AsyncCoverImage(url: item.book.cover)
.frame(width: 96, height: 138)
.clipShape(RoundedRectangle(cornerRadius: 10))
.shadow(color: .black.opacity(0.55), radius: 12, y: 6)
@@ -215,14 +206,7 @@ private struct ContinueReadingCard: View {
var body: some View {
VStack(alignment: .leading, spacing: 6) {
ZStack(alignment: .bottomTrailing) {
KFImage(URL(string: item.book.cover))
.resizable()
.placeholder {
RoundedRectangle(cornerRadius: 8)
.fill(Color(.systemGray5))
.overlay(Image(systemName: "book.closed").foregroundStyle(.secondary))
}
.scaledToFill()
AsyncCoverImage(url: item.book.cover)
.frame(width: 110, height: 158)
.clipShape(RoundedRectangle(cornerRadius: 8))
@@ -258,14 +242,7 @@ private struct ShelfBookCard: View {
var body: some View {
VStack(alignment: .leading, spacing: 6) {
KFImage(URL(string: book.cover))
.resizable()
.placeholder {
RoundedRectangle(cornerRadius: 8)
.fill(Color(.systemGray5))
.overlay(Image(systemName: "book.closed").foregroundStyle(.secondary))
}
.scaledToFill()
AsyncCoverImage(url: book.cover)
.frame(width: 110, height: 158)
.clipShape(RoundedRectangle(cornerRadius: 8))
.shadow(color: .black.opacity(0.12), radius: 4, y: 2)

View File

@@ -235,56 +235,6 @@ struct LibraryView: View {
}
}
// MARK: - Genre filter chip
private struct FilterChipView: View {
let label: String
let isSelected: Bool
let action: () -> Void
var body: some View {
Button(action: action) {
Text(label)
.font(.caption.weight(isSelected ? .semibold : .regular))
.padding(.horizontal, 12)
.padding(.vertical, 6)
.background(
Capsule()
.fill(isSelected ? Color.amber : Color(.systemGray5))
)
.foregroundStyle(isSelected ? .white : .primary)
}
.buttonStyle(.plain)
}
}
// MARK: - Sort chip
private struct SortChip: View {
let label: String
let isSelected: Bool
let action: () -> Void
var body: some View {
Button(action: action) {
Text(label)
.font(.subheadline.weight(isSelected ? .semibold : .regular))
.padding(.horizontal, 14)
.padding(.vertical, 6)
.background(
Capsule()
.fill(isSelected ? Color.amber.opacity(0.15) : Color(.systemGray6))
.overlay(
Capsule()
.stroke(isSelected ? Color.amber : .clear, lineWidth: 1.5)
)
)
.foregroundStyle(isSelected ? .amber : .primary)
}
.buttonStyle(.plain)
}
}
// MARK: - Library book card (3-column)
private struct LibraryBookCard: View {

View File

@@ -47,7 +47,7 @@ struct MiniPlayerView: View {
// Previous chapter button
if audioPlayer.status == .ready {
Button {
if let prev = audioPlayer.absolutePrevChapter {
if let prev = audioPlayer.prevChapter {
NotificationCenter.default.post(
name: .skipToPrevChapter,
object: nil,
@@ -62,8 +62,8 @@ struct MiniPlayerView: View {
.contentShape(Rectangle())
}
.buttonStyle(.plain)
.disabled(audioPlayer.absolutePrevChapter == nil)
.opacity(audioPlayer.absolutePrevChapter == nil ? 0.4 : 1.0)
.disabled(audioPlayer.prevChapter == nil)
.opacity(audioPlayer.prevChapter == nil ? 0.4 : 1.0)
}
// Status indicator or play/pause control
@@ -92,7 +92,7 @@ struct MiniPlayerView: View {
// Next chapter button
if audioPlayer.status == .ready {
Button {
if let next = audioPlayer.absoluteNextChapter {
if let next = audioPlayer.nextChapter {
NotificationCenter.default.post(
name: .skipToNextChapter,
object: nil,
@@ -124,8 +124,8 @@ struct MiniPlayerView: View {
.contentShape(Rectangle())
}
.buttonStyle(.plain)
.disabled(audioPlayer.absoluteNextChapter == nil)
.opacity(audioPlayer.absoluteNextChapter == nil ? 0.4 : 1.0)
.disabled(audioPlayer.nextChapter == nil)
.opacity(audioPlayer.nextChapter == nil ? 0.4 : 1.0)
}
}
}
@@ -342,9 +342,9 @@ struct FullPlayerView: View {
PlayerChapterSkipButton(
systemName: "backward.end.fill",
size: 30,
disabled: audioPlayer.absolutePrevChapter == nil
disabled: audioPlayer.prevChapter == nil
) {
if let prev = audioPlayer.absolutePrevChapter {
if let prev = audioPlayer.prevChapter {
onDismiss()
NotificationCenter.default.post(
name: .skipToPrevChapter, object: nil,
@@ -364,10 +364,10 @@ struct FullPlayerView: View {
PlayerChapterSkipButton(
systemName: "forward.end.fill",
size: 30,
disabled: audioPlayer.absoluteNextChapter == nil,
disabled: audioPlayer.nextChapter == nil,
prefetching: audioPlayer.nextPrefetchStatus == .prefetching
) {
if let next = audioPlayer.absoluteNextChapter {
if let next = audioPlayer.nextChapter {
onDismiss()
NotificationCenter.default.post(
name: .skipToNextChapter, object: nil,