Implemented the RepositoriesView view and its respective view model in the app target.

This commit is contained in:
Javier Cicchelli 2024-10-22 21:40:59 +02:00
parent 2f8e3a094d
commit cd8adb6f66
3 changed files with 205 additions and 0 deletions

View File

@ -42,6 +42,57 @@
}
}
},
"settings.button.add-repository.text" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Add repository"
}
}
}
},
"settings.column.active.text" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Active"
}
}
}
},
"settings.column.folder.text" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Folder"
}
}
}
},
"settings.column.name.text" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Name"
}
}
}
},
"settings.item.active.text" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : " "
}
}
}
},
"settings.tab-bar.repositories.text" : {
"localizations" : {
"en" : {

View File

@ -0,0 +1,37 @@
//
// RepositoriesViewModel.swift
// Piper ~ App
//
// Created by Javier Cicchelli on 21/10/2024.
// Copyright © 2024 Röck+Cöde. All rights reserved.
//
import Foundation
import Observation
import SwiftData
@Observable
final class RepositoriesViewModel {
// MARK: Properties
var fileImporterOpened: Bool = false
var rowsSelected: Set<Repository.ID> = []
// MARK: Functions
func addRepository(
_ result: Result<URL, any Error>,
into context: ModelContext
) {
do {
let url = try result.get()
let repository = Repository(url)
context.insert(repository)
} catch {
// TODO: Handle this error gracefully.
}
}
}

View File

@ -0,0 +1,117 @@
//
// RepositoriesView.swift
// Piper ~ App
//
// Created by Javier Cicchelli on 14/10/2024.
// Copyright © 2024 Röck+Cöde. All rights reserved.
//
import SwiftData
import SwiftUI
struct RepositoriesView: View {
// MARK: Properties
@Environment(\.modelContext) private var modelContext
@Query(sort: \Repository.addedAt)
private var repositories: [Repository]
@State private var viewModel: RepositoriesViewModel = .init()
// MARK: Body
var body: some View {
HStack(
alignment: .top,
spacing: Layout.spacingHorizontal
) {
Table(
repositories,
selection: $viewModel.rowsSelected
) {
TableColumn("settings.column.active.text") { repository in
HStack {
Toggle("settings.item.active.text", isOn: .init {
repository.active
} set: {
repository.active = $0
})
}
}
TableColumn("settings.column.name.text") { repository in
Text(repository.name)
.fontWeight(.semibold)
.foregroundStyle(.primary)
}
TableColumn("settings.column.folder.text") { repository in
Text(repository.folder)
.fontWeight(.regular)
.foregroundStyle(.secondary)
}
}
VStack {
Button("settings.button.add-repository.text") {
viewModel.fileImporterOpened = true
}
.fileImporter(
isPresented: $viewModel.fileImporterOpened,
allowedContentTypes: [.pdf]
) {
viewModel.addRepository($0, into: modelContext)
}
}
}
}
}
// MARK: - Layout
private extension RepositoriesView {
enum Layout {
static let spacingHorizontal = CGFloat(16)
}
}
// MARK: - Previews
@available(macOS 15.0, *)
#Preview(
"Repositories view when no repositories found (macOS 15)",
traits: .emptyData
) {
RepositoriesView()
.scenePadding()
}
@available(macOS, obsoleted: 15)
#Preview("Repositories view when no repositories found (macOS 14)") {
MenuBarView()
.modelContainer(.preview)
.scenePadding()
}
@available(macOS 15.0, *)
#Preview(
"Repositories view when repositories found (macOS 15)",
traits: .sampleData
) {
RepositoriesView()
.scenePadding()
}
@available(macOS, obsoleted: 15)
#Preview("Repositories view when repositories found (macOS 14)") {
let container = ModelContainer.preview
Repository.samples(in: container)
return RepositoriesView()
.modelContainer(container)
.scenePadding()
}