feat(ios): tab tabanlı navigasyon ve okuma durumu takibi ekle

This commit is contained in:
2026-02-11 18:26:17 +03:00
parent 52212f015b
commit 362b9b7d1b
16 changed files with 976 additions and 442 deletions

View File

@@ -0,0 +1,68 @@
import SwiftUI
struct BookCardView: View {
let title: String
let author: String
let coverURL: URL?
let status: ReadingStatus
let progress: Double?
var body: some View {
VStack(alignment: .leading, spacing: Theme.Spacing.small) {
AsyncImage(url: coverURL) { phase in
switch phase {
case .success(let image):
image.resizable().scaledToFill()
default:
ZStack {
RoundedRectangle(cornerRadius: Theme.Radius.image)
.fill(Color.gray.opacity(0.22))
Image(systemName: "book.closed")
.font(.title2)
.foregroundStyle(.secondary)
}
}
}
.frame(height: 170)
.clipShape(RoundedRectangle(cornerRadius: Theme.Radius.image, style: .continuous))
Text(title)
.font(.headline)
.lineLimit(2)
.minimumScaleFactor(0.85)
Text(author.isEmpty ? "Unknown Author" : author)
.font(.subheadline)
.foregroundStyle(.secondary)
.lineLimit(1)
HStack(spacing: Theme.Spacing.xSmall) {
Image(systemName: status.symbol)
Text(status.title)
.lineLimit(1)
}
.font(.caption.weight(.semibold))
.padding(.horizontal, 8)
.padding(.vertical, 5)
.foregroundStyle(status.color)
.background(status.color.opacity(0.14), in: Capsule())
if let progress, status == .reading {
ProgressView(value: progress)
.tint(status.color)
.animation(.easeOut(duration: 0.35), value: progress)
.accessibilityLabel("Reading progress")
.accessibilityValue("\(Int(progress * 100)) percent")
}
}
.padding(Theme.Spacing.medium)
.background(.background, in: RoundedRectangle(cornerRadius: Theme.Radius.card, style: .continuous))
.overlay {
RoundedRectangle(cornerRadius: Theme.Radius.card, style: .continuous)
.stroke(Color.primary.opacity(0.06), lineWidth: 1)
}
.shadow(color: Theme.Shadow.card.color, radius: Theme.Shadow.card.radius, y: Theme.Shadow.card.y)
.accessibilityElement(children: .combine)
.accessibilityLabel("\(title), \(author), \(status.title)")
}
}

View File

@@ -0,0 +1,34 @@
import SwiftUI
struct EmptyStateView: View {
let symbol: String
let title: String
let message: String
let buttonTitle: String?
let action: (() -> Void)?
var body: some View {
VStack(spacing: Theme.Spacing.medium) {
Image(systemName: symbol)
.font(.system(size: 44, weight: .semibold))
.foregroundStyle(.secondary)
Text(title)
.font(.title3.weight(.semibold))
Text(message)
.font(.body)
.foregroundStyle(.secondary)
.multilineTextAlignment(.center)
if let buttonTitle, let action {
Button(buttonTitle, action: action)
.buttonStyle(.borderedProminent)
}
}
.padding(24)
.frame(maxWidth: .infinity)
.background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 20, style: .continuous))
.padding(.horizontal, 20)
}
}

View File

@@ -26,4 +26,21 @@ enum Theme {
static func headerSerif(size: CGFloat) -> Font {
.custom("NewYork-Regular", size: size, relativeTo: .largeTitle)
}
enum Spacing {
static let xSmall: CGFloat = 6
static let small: CGFloat = 10
static let medium: CGFloat = 16
static let large: CGFloat = 24
}
enum Radius {
static let card: CGFloat = 14
static let image: CGFloat = 10
static let pill: CGFloat = 999
}
enum Shadow {
static let card = (color: Color.black.opacity(0.14), radius: CGFloat(8), y: CGFloat(4))
}
}