feat: ios mobil arayüz tasarımı

This commit is contained in:
2026-02-11 18:06:35 +03:00
parent 69884db0ab
commit 261b2f58cc
42 changed files with 2501 additions and 0 deletions

View File

@@ -0,0 +1,53 @@
import Foundation
import SwiftUI
@MainActor
final class AppRouter: ObservableObject {
enum Route: Hashable {
case addBooks
case category(name: String)
case detail(BookRemote)
}
@Published var isAuthenticated = false
@Published var path: [Route] = []
func resetToHome() {
path.removeAll()
}
}
struct AppDependencies {
let apiClient: APIClientProtocol
let authService: AuthServiceProtocol
let booksService: BooksServiceProtocol
let keychain: KeychainStoreProtocol
let imageCache: ImageCacheProtocol
static func live() -> AppDependencies {
let config = URLSessionConfiguration.default
config.waitsForConnectivity = false
config.timeoutIntervalForRequest = 8
config.timeoutIntervalForResource = 15
let session = URLSession(configuration: config)
let client = APIClient(baseURL: Bundle.main.apiBaseURL, session: session)
return AppDependencies(
apiClient: client,
authService: AuthService(client: client),
booksService: BooksService(client: client),
keychain: KeychainStore(),
imageCache: ImageCache.shared
)
}
}
private struct DependenciesKey: EnvironmentKey {
static let defaultValue = AppDependencies.live()
}
extension EnvironmentValues {
var dependencies: AppDependencies {
get { self[DependenciesKey.self] }
set { self[DependenciesKey.self] = newValue }
}
}

View File

@@ -0,0 +1,72 @@
import SwiftUI
import SwiftData
@main
struct BookibraApp: App {
@StateObject private var router = AppRouter()
private let dependencies = AppDependencies.live()
private let container: ModelContainer
init() {
do {
container = try ModelContainer(for: LibraryBook.self)
} catch {
fatalError("SwiftData container oluşturulamadı: \(error)")
}
}
var body: some Scene {
WindowGroup {
RootView()
.environmentObject(router)
.environment(\.dependencies, dependencies)
.modelContainer(container)
}
}
}
private struct RootView: View {
@EnvironmentObject private var router: AppRouter
@Environment(\.dependencies) private var dependencies
var body: some View {
NavigationStack(path: $router.path) {
Group {
if router.isAuthenticated {
HomeView(viewModel: HomeViewModel())
} else {
AuthView(viewModel: AuthViewModel(authService: dependencies.authService, keychain: dependencies.keychain))
}
}
.navigationDestination(for: AppRouter.Route.self) { route in
switch route {
case .addBooks:
AddBooksView(viewModel: AddBooksViewModel(booksService: dependencies.booksService))
case .category(let name):
CategoryListView(viewModel: CategoryViewModel(categoryName: name))
case .detail(let book):
BookDetailView(viewModel: BookDetailViewModel(book: book))
}
}
}
.task {
await bootstrapSession()
}
}
@MainActor
private func bootstrapSession() async {
let token = dependencies.keychain.read(for: AuthViewModel.tokenKey)
guard let token, !token.isEmpty else {
router.isAuthenticated = false
return
}
do {
_ = try await dependencies.authService.profile(token: token)
router.isAuthenticated = true
} catch {
router.isAuthenticated = false
}
}
}