119 lines
3.2 KiB
Swift
119 lines
3.2 KiB
Swift
import SwiftUI
|
|
|
|
struct PostList: View {
|
|
|
|
@EnvironmentObject
|
|
private var content: Content
|
|
|
|
@Environment(\.language)
|
|
private var language: ContentLanguage
|
|
|
|
@State
|
|
private var newPostId = ""
|
|
|
|
@State
|
|
private var selected: Post? = nil
|
|
|
|
@State
|
|
private var showNewPostView = false
|
|
|
|
@State
|
|
private var newPostIdIsValid = false
|
|
|
|
private let allowedCharactersInPostId = CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "-")).inverted
|
|
|
|
private var cleanPostId: String {
|
|
newPostId.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
}
|
|
|
|
var body: some View {
|
|
NavigationSplitView {
|
|
List(content.posts, selection: $selected) { post in
|
|
Text(post.localized(in: language).title)
|
|
.tag(post)
|
|
}
|
|
.frame(minWidth: 200)
|
|
.toolbar {
|
|
ToolbarItem(placement: .primaryAction) {
|
|
Button(action: { showNewPostView = true }) {
|
|
Label("New post", systemSymbol: .plus)
|
|
}
|
|
}
|
|
}
|
|
} content: {
|
|
if let selected {
|
|
PostContentView(post: selected)
|
|
.layoutPriority(1)
|
|
} else {
|
|
HStack {
|
|
Spacer()
|
|
Text("Select a post to show the content")
|
|
.font(.largeTitle)
|
|
.foregroundColor(.secondary)
|
|
Spacer()
|
|
}.layoutPriority(1)
|
|
}
|
|
} detail: {
|
|
if let selected {
|
|
PostDetailView(post: selected)
|
|
.frame(minWidth: 280)
|
|
} else {
|
|
Text("No post selected")
|
|
.frame(minWidth: 280)
|
|
}
|
|
}
|
|
.sheet(isPresented: $showNewPostView,
|
|
onDismiss: addNewPost) {
|
|
TextEntrySheet(
|
|
title: "Enter the id for the new post",
|
|
text: $newPostId,
|
|
isValid: $newPostIdIsValid)
|
|
}
|
|
.onChange(of: newPostId) { _, newValue in
|
|
newPostIdIsValid = isValid(id: newValue)
|
|
}
|
|
.onAppear {
|
|
if selected == nil {
|
|
selected = content.posts.first
|
|
}
|
|
}
|
|
}
|
|
|
|
private func isValid(id: String) -> Bool {
|
|
let id = cleanPostId
|
|
guard id != "" else {
|
|
return false
|
|
}
|
|
|
|
guard !content.posts.contains(where: { $0.id == id }) else {
|
|
return false
|
|
}
|
|
// Only allow alphanumeric characters and hyphens
|
|
return id.rangeOfCharacter(from: allowedCharactersInPostId) == nil
|
|
}
|
|
|
|
private func addNewPost() {
|
|
let id = cleanPostId
|
|
guard isValid(id: id) else {
|
|
return
|
|
}
|
|
|
|
let post = Post(
|
|
id: id,
|
|
isDraft: true,
|
|
createdDate: .now,
|
|
startDate: .now,
|
|
endDate: nil,
|
|
tags: [],
|
|
german: .init(title: "Titel", content: "Text"),
|
|
english: .init(title: "Title", content: "Text"))
|
|
content.posts.insert(post, at: 0)
|
|
selected = post
|
|
}
|
|
}
|
|
|
|
#Preview {
|
|
PostList()
|
|
.environmentObject(Content())
|
|
}
|