Unified detail views, model
This commit is contained in:
@ -35,4 +35,11 @@ extension Content {
|
||||
func tag(_ tagId: String) -> Tag? {
|
||||
tags.first { $0.id == tagId }
|
||||
}
|
||||
|
||||
func navigationBar(in language: ContentLanguage) -> [NavigationBar.Link] {
|
||||
settings.navigationItems.map {
|
||||
.init(text: $0.title(in: language),
|
||||
url: $0.absoluteUrl(in: language))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ extension Content {
|
||||
|
||||
private func convert(_ tag: LocalizedTagFile, images: [String : FileResource]) -> LocalizedTag {
|
||||
LocalizedTag(
|
||||
content: self,
|
||||
urlComponent: tag.urlComponent,
|
||||
name: tag.name,
|
||||
subtitle: tag.subtitle,
|
||||
@ -14,8 +15,9 @@ extension Content {
|
||||
|
||||
private func convert(_ post: LocalizedPostFile, images: [String : FileResource]) -> LocalizedPost {
|
||||
LocalizedPost(
|
||||
content: self,
|
||||
title: post.title,
|
||||
content: post.content,
|
||||
text: post.content,
|
||||
lastModified: post.lastModifiedDate,
|
||||
images: post.images.compactMap { images[$0] },
|
||||
linkPreviewImage: post.linkPreviewImage.map { images[$0] },
|
||||
@ -107,8 +109,8 @@ extension Content {
|
||||
let tagOverview = tagOverviewData.map { file in
|
||||
TagOverviewPage(
|
||||
content: self,
|
||||
german: .init(file: file.german, image: file.german.linkPreviewImage.map { files[$0] }),
|
||||
english: .init(file: file.english, image: file.english.linkPreviewImage.map { files[$0] }))
|
||||
german: .init(content: self, file: file.german, image: file.german.linkPreviewImage.map { files[$0] }),
|
||||
english: .init(content: self, file: file.english, image: file.english.linkPreviewImage.map { files[$0] }))
|
||||
}
|
||||
|
||||
self.tags = tags.values.sorted()
|
||||
|
@ -95,7 +95,7 @@ private extension LocalizedPost {
|
||||
var postFile: LocalizedPostFile {
|
||||
.init(images: images.map { $0.id },
|
||||
title: title.nonEmpty,
|
||||
content: content,
|
||||
content: text,
|
||||
lastModifiedDate: lastModified,
|
||||
linkPreviewImage: linkPreviewImage?.id,
|
||||
linkPreviewTitle: linkPreviewTitle,
|
||||
|
@ -18,6 +18,10 @@ extension Content {
|
||||
!posts.contains { $0.id == id }
|
||||
}
|
||||
|
||||
func isNewIdForFile(_ id: String) -> Bool {
|
||||
!files.contains { $0.id == id }
|
||||
}
|
||||
|
||||
func isValidIdForTagOrPageOrPost(_ id: String) -> Bool {
|
||||
id.rangeOfCharacter(from: Content.disallowedCharactersInIds) == nil
|
||||
}
|
||||
@ -26,6 +30,13 @@ extension Content {
|
||||
id.rangeOfCharacter(from: Content.disallowedCharactersInFileIds) == nil
|
||||
}
|
||||
|
||||
func containsPage(withUrlComponent urlComponent: String) -> Bool {
|
||||
pages.contains {
|
||||
$0.german.urlString == urlComponent ||
|
||||
$0.english.urlString == urlComponent
|
||||
}
|
||||
}
|
||||
|
||||
func containsTag(withUrlComponent urlComponent: String) -> Bool {
|
||||
(tagOverview?.contains(urlComponent: urlComponent) ?? false) ||
|
||||
tags.contains { $0.contains(urlComponent: urlComponent) }
|
||||
|
@ -111,6 +111,13 @@ final class FileResource: Item {
|
||||
|
||||
// MARK: File
|
||||
|
||||
func isValid(id: String) -> Bool {
|
||||
!id.isEmpty &&
|
||||
content.isValidIdForFile(id) &&
|
||||
content.isNewIdForFile(id)
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
func update(id newId: String) -> Bool {
|
||||
guard !isExternallyStored else {
|
||||
id = newId
|
||||
|
@ -34,11 +34,11 @@ final class TagOverviewPage: Item {
|
||||
}
|
||||
|
||||
private func internalPath(for language: ContentLanguage) -> String {
|
||||
content.settings.paths.tagsOutputFolderPath + "/" + localized(in: language).urlString
|
||||
content.settings.paths.tagsOutputFolderPath + "/" + localized(in: language).urlComponent
|
||||
}
|
||||
|
||||
func contains(urlComponent: String) -> Bool {
|
||||
english.urlString == urlComponent || german.urlString == urlComponent
|
||||
english.urlComponent == urlComponent || german.urlComponent == urlComponent
|
||||
}
|
||||
|
||||
var file: TagOverviewFile {
|
||||
@ -53,16 +53,16 @@ extension TagOverviewPage: LocalizedItem {
|
||||
|
||||
final class LocalizedTagOverviewPage: ObservableObject {
|
||||
|
||||
unowned let content: Content
|
||||
|
||||
@Published
|
||||
var title: String
|
||||
|
||||
/**
|
||||
The string to use when creating the url for the page.
|
||||
|
||||
Defaults to ``id`` if unset.
|
||||
*/
|
||||
@Published
|
||||
var urlString: String
|
||||
var urlComponent: String
|
||||
|
||||
@Published
|
||||
var linkPreviewImage: FileResource?
|
||||
@ -73,27 +73,35 @@ final class LocalizedTagOverviewPage: ObservableObject {
|
||||
@Published
|
||||
var linkPreviewDescription: String?
|
||||
|
||||
init(title: String, urlString: String, linkPreviewImage: FileResource? = nil, linkPreviewTitle: String? = nil, linkPreviewDescription: String? = nil) {
|
||||
init(content: Content, title: String, urlString: String, linkPreviewImage: FileResource? = nil, linkPreviewTitle: String? = nil, linkPreviewDescription: String? = nil) {
|
||||
self.content = content
|
||||
self.title = title
|
||||
self.urlString = urlString
|
||||
self.urlComponent = urlString
|
||||
self.linkPreviewImage = linkPreviewImage
|
||||
self.linkPreviewTitle = linkPreviewTitle
|
||||
self.linkPreviewDescription = linkPreviewDescription
|
||||
}
|
||||
|
||||
init(file: LocalizedTagOverviewFile, image: FileResource?) {
|
||||
init(content: Content, file: LocalizedTagOverviewFile, image: FileResource?) {
|
||||
self.content = content
|
||||
self.title = file.title
|
||||
self.urlString = file.url
|
||||
self.urlComponent = file.url
|
||||
self.linkPreviewImage = image
|
||||
self.linkPreviewTitle = file.linkPreviewTitle
|
||||
self.linkPreviewDescription = file.linkPreviewDescription
|
||||
}
|
||||
|
||||
var file: LocalizedTagOverviewFile {
|
||||
.init(url: urlString,
|
||||
.init(url: urlComponent,
|
||||
title: title,
|
||||
linkPreviewImage: linkPreviewImage?.id,
|
||||
linkPreviewTitle: linkPreviewTitle,
|
||||
linkPreviewDescription: linkPreviewDescription)
|
||||
}
|
||||
|
||||
func isValid(urlComponent: String) -> Bool {
|
||||
!urlComponent.isEmpty &&
|
||||
content.isValidIdForTagOrPageOrPost(urlComponent) &&
|
||||
!content.containsTag(withUrlComponent: urlComponent)
|
||||
}
|
||||
}
|
||||
|
@ -89,4 +89,9 @@ final class LocalizedPage: ObservableObject {
|
||||
self.linkPreviewTitle = linkPreviewTitle
|
||||
self.linkPreviewDescription = linkPreviewDescription
|
||||
}
|
||||
|
||||
func isValid(urlComponent: String) -> Bool {
|
||||
content.isValidIdForTagOrPageOrPost(urlComponent) &&
|
||||
!content.containsPage(withUrlComponent: urlComponent)
|
||||
}
|
||||
}
|
||||
|
@ -3,11 +3,13 @@ import SwiftUI
|
||||
|
||||
final class LocalizedPost: ObservableObject {
|
||||
|
||||
unowned let content: Content
|
||||
|
||||
@Published
|
||||
var title: String
|
||||
|
||||
@Published
|
||||
var content: String
|
||||
var text: String
|
||||
|
||||
@Published
|
||||
var lastModified: Date?
|
||||
@ -24,15 +26,17 @@ final class LocalizedPost: ObservableObject {
|
||||
@Published
|
||||
var linkPreviewDescription: String?
|
||||
|
||||
init(title: String? = nil,
|
||||
content: String,
|
||||
init(content: Content,
|
||||
title: String? = nil,
|
||||
text: String,
|
||||
lastModified: Date? = nil,
|
||||
images: [FileResource] = [],
|
||||
linkPreviewImage: FileResource? = nil,
|
||||
linkPreviewTitle: String? = nil,
|
||||
linkPreviewDescription: String? = nil) {
|
||||
self.title = title ?? ""
|
||||
self.content = content
|
||||
self.title = title ?? ""
|
||||
self.text = text
|
||||
self.lastModified = lastModified
|
||||
self.images = images
|
||||
self.linkPreviewImage = linkPreviewImage
|
||||
|
@ -2,6 +2,8 @@ import Foundation
|
||||
|
||||
final class LocalizedTag: ObservableObject {
|
||||
|
||||
unowned let content: Content
|
||||
|
||||
@Published
|
||||
var urlComponent: String
|
||||
|
||||
@ -22,12 +24,14 @@ final class LocalizedTag: ObservableObject {
|
||||
/// The original url in the previous site layout
|
||||
let originalUrl: String?
|
||||
|
||||
init(urlComponent: String,
|
||||
init(content: Content,
|
||||
urlComponent: String,
|
||||
name: String,
|
||||
subtitle: String? = nil,
|
||||
description: String? = nil,
|
||||
thumbnail: FileResource? = nil,
|
||||
originalUrl: String? = nil) {
|
||||
self.content = content
|
||||
self.urlComponent = urlComponent
|
||||
self.name = name
|
||||
self.subtitle = subtitle
|
||||
@ -35,4 +39,9 @@ final class LocalizedTag: ObservableObject {
|
||||
self.linkPreviewImage = thumbnail
|
||||
self.originalUrl = originalUrl
|
||||
}
|
||||
|
||||
func isValid(urlComponent: String) -> Bool {
|
||||
content.isValidIdForTagOrPageOrPost(urlComponent) &&
|
||||
!content.containsTag(withUrlComponent: urlComponent)
|
||||
}
|
||||
}
|
||||
|
@ -66,9 +66,16 @@ final class Page: Item {
|
||||
super.init(content: content, id: id)
|
||||
}
|
||||
|
||||
func isValid(id: String) -> Bool {
|
||||
!id.isEmpty &&
|
||||
content.isValidIdForTagOrPageOrPost(id) &&
|
||||
content.isNewIdForPage(id)
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
func update(id newId: String) -> Bool {
|
||||
guard content.storage.move(page: id, to: newId) else {
|
||||
print("Failed to move file of page \(id)")
|
||||
print("Failed to move files of page \(id)")
|
||||
return false
|
||||
}
|
||||
id = newId
|
||||
|
@ -65,6 +65,13 @@ final class Post: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
func isValid(id: String) -> Bool {
|
||||
!id.isEmpty &&
|
||||
content.isValidIdForTagOrPageOrPost(id) &&
|
||||
content.isNewIdForPost(id)
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
func update(id newId: String) -> Bool {
|
||||
do {
|
||||
try content.storage.move(post: id, to: newId)
|
||||
|
@ -13,9 +13,9 @@ final class Tag: Item {
|
||||
|
||||
override init(content: Content, id: String) {
|
||||
self.isVisible = true
|
||||
self.english = .init(urlComponent: id, name: id)
|
||||
self.english = .init(content: content, urlComponent: id, name: id)
|
||||
let deId = id + "-" + ContentLanguage.german.rawValue
|
||||
self.german = .init(urlComponent: deId, name: deId)
|
||||
self.german = .init(content: content, urlComponent: deId, name: deId)
|
||||
super.init(content: content, id: id)
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user