Move required files to settings

This commit is contained in:
Christoph Hagen 2025-02-24 19:12:15 +01:00
parent ccf1ef3734
commit cdc84cdf4c
11 changed files with 54 additions and 91 deletions

View File

@ -1,9 +1,4 @@
#warning("Add remaining header elements")
// <meta name="msapplication-TileColor" content="#da532c">
// <meta name="theme-color" content="#ffffff">
// <meta name="msapplication-config" content="/assets/icons/browserconfig.xml?v=1">
// TODO: Move to settings?
extension HeaderElement {

View File

@ -312,8 +312,6 @@ extension Content {
let results = results.makeResults(for: page, in: language)
let pageGenerator = PageGenerator(content: self)
results.require(files: page.requiredFiles)
let relativePageUrl = page.absoluteUrl(in: language)
let filePath = relativePageUrl + ".html"
let pageUrl = settings.general.url + relativePageUrl

View File

@ -40,10 +40,6 @@ final class Page: Item, DateItem, LocalizedItem {
@Published
var tags: [Tag]
/// Additional files to copy, because the page content references them
@Published
var requiredFiles: [FileResource]
var savedData: Data?
init(content: Content,
@ -56,8 +52,7 @@ final class Page: Item, DateItem, LocalizedItem {
endDate: Date?,
german: LocalizedPage,
english: LocalizedPage,
tags: [Tag],
requiredFiles: [FileResource]) {
tags: [Tag]) {
self.externalLink = externalLink
self.isDraft = isDraft
self.createdDate = createdDate
@ -68,7 +63,6 @@ final class Page: Item, DateItem, LocalizedItem {
self.german = german
self.english = english
self.tags = tags
self.requiredFiles = requiredFiles
super.init(content: content, id: id)
}
@ -186,9 +180,6 @@ final class Page: Item, DateItem, LocalizedItem {
}
func remove(_ file: FileResource) {
if requiredFiles.contains(file) {
requiredFiles.remove(file)
}
english.linkPreview.remove(file)
german.linkPreview.remove(file)
}
@ -210,8 +201,7 @@ extension Page: StorageItem {
endDate: data.endDate,
german: .init(context: context, data: data.german),
english: .init(context: context, data: data.english),
tags: data.tags.compactMap(context.tag),
requiredFiles: data.requiredFiles?.compactMap(context.file) ?? [])
tags: data.tags.compactMap(context.tag))
savedData = data
}
@ -226,7 +216,6 @@ extension Page: StorageItem {
let endDate: Date?
let german: LocalizedPage.Data
let english: LocalizedPage.Data
let requiredFiles: [String]?
}
@ -240,8 +229,7 @@ extension Page: StorageItem {
startDate: startDate,
endDate: endDate,
german: german.data,
english: english.data,
requiredFiles: requiredFiles.nonEmpty?.map { $0.id }.sorted())
english: english.data)
}
func saveToDisk(_ data: Data) -> Bool {

View File

@ -172,8 +172,7 @@ final class Post: Item, DateItem, LocalizedItem {
endDate: endDate,
german: german,
english: english,
tags: tags,
requiredFiles: [])
tags: tags)
}
}

View File

@ -27,7 +27,10 @@ final class GeneralSettings: ObservableObject {
@Published
var urlForPushNotification: String?
init(url: String, linkPreviewImageWidth: Int, linkPreviewImageHeight: Int, remoteUserForUpload: String, remotePortForUpload: Int, remotePathForUpload: String, urlForPushNotification: String?) {
@Published
var requiredFiles: [FileResource]
init(url: String, linkPreviewImageWidth: Int, linkPreviewImageHeight: Int, remoteUserForUpload: String, remotePortForUpload: Int, remotePathForUpload: String, urlForPushNotification: String?, requiredFiles: [FileResource]) {
self.url = url
self.linkPreviewImageWidth = linkPreviewImageWidth
self.linkPreviewImageHeight = linkPreviewImageHeight
@ -35,12 +38,13 @@ final class GeneralSettings: ObservableObject {
self.remotePortForUpload = remotePortForUpload
self.remotePathForUpload = remotePathForUpload
self.urlForPushNotification = urlForPushNotification
self.requiredFiles = requiredFiles
}
}
extension GeneralSettings {
convenience init(data: Data) {
convenience init(context: LoadingContext, data: Data) {
self.init(
url: data.url,
linkPreviewImageWidth: data.linkPreviewImageWidth,
@ -48,7 +52,8 @@ extension GeneralSettings {
remoteUserForUpload: data.remoteUserForUpload,
remotePortForUpload: data.remotePortForUpload,
remotePathForUpload: data.remotePathForUpload,
urlForPushNotification: data.urlForPushNotification)
urlForPushNotification: data.urlForPushNotification,
requiredFiles: data.requiredFiles?.compactMap(context.file) ?? [])
}
var data: Data {
@ -59,7 +64,8 @@ extension GeneralSettings {
remoteUserForUpload: remoteUserForUpload,
remotePortForUpload: remotePortForUpload,
remotePathForUpload: remotePathForUpload,
urlForPushNotification: urlForPushNotification)
urlForPushNotification: urlForPushNotification,
requiredFiles: requiredFiles.nonEmpty?.map { $0.id }.sorted())
}
struct Data: Codable, Equatable {
@ -70,5 +76,6 @@ extension GeneralSettings {
let remotePortForUpload: Int
let remotePathForUpload: String
let urlForPushNotification: String?
let requiredFiles: [String]?
}
}

View File

@ -57,7 +57,7 @@ extension Settings {
convenience init(context: LoadingContext, data: Settings.Data) {
self.init(
general: .init(data: data.general),
general: .init(context: context, data: data.general),
paths: .init(data: data.paths),
navigation: .init(context: context, data: data.navigation),
posts: .init(context: context, data: data.posts),
@ -112,7 +112,8 @@ extension GeneralSettings {
remoteUserForUpload: "user",
remotePortForUpload: 22,
remotePathForUpload: "/home/user/web",
urlForPushNotification: nil)
urlForPushNotification: nil,
requiredFiles: [])
}
extension AudioPlayerSettings {

View File

@ -29,8 +29,7 @@ extension Page {
originalUrl: "projects/electronics/my-first-project/en.html"),
tags: [
content.tags.first(where: { $0.id == "electronics" })!
],
requiredFiles: [])
])
]
}

View File

@ -431,30 +431,6 @@ final class Storage: ObservableObject {
return contentScope.encode(settings, to: settingsDataFileName)
}
// MARK: Image generation data
func calculateImages(generatedBy imageSet: Set<String>, in folder: String) -> [String : Set<String>] {
#warning("TODO: Move to file resource")
guard let outputScope else { return [:] }
guard let allImages = outputScope.fileNames(inRelativeFolder: folder) else {
print("Failed to get list of generated images in output folder")
return [:]
}
guard !allImages.isEmpty else {
print("No images found in output folder \(folder)")
return [:]
}
print("Found \(allImages.count) generated images")
let images = Set(allImages)
return imageSet.reduce(into: [:]) { result, imageName in
let prefix = imageName.fileNameWithoutExtension + "@"
let versions = images.filter { $0.hasPrefix(prefix) }
if !versions.isEmpty {
result[imageName] = Set(versions)
}
}
}
// MARK: Output files
/**

View File

@ -79,8 +79,7 @@ struct AddPageView: View {
english: .init(content: content,
urlString: "page",
title: "A Title"),
tags: [],
requiredFiles: [])
tags: [])
content.add(page)
selectedPage = page
dismissSheet()

View File

@ -12,9 +12,6 @@ struct PageDetailView: View {
@ObservedObject
private var page: Page
@State
private var showFileSelectionSheet = false
private var transferImage: (language: ContentLanguage, image: FileResource)? {
page.localized(in: language.next).linkPreview.image.map { (language.next, $0) }
}
@ -23,14 +20,6 @@ struct PageDetailView: View {
self.page = page
}
private var requiredFilesText: String {
switch page.requiredFiles.count {
case 0: return "No files"
case 1: return "1 file"
default: return "\(page.requiredFiles.count) files"
}
}
var body: some View {
ScrollView {
VStack(alignment: .leading) {
@ -79,24 +68,6 @@ struct PageDetailView: View {
footer: "The date when the page content ended")
.disabled(page.isExternalUrl)
GenericPropertyView(
title: "Required files",
footer: "The additional files required by the page") {
HStack {
Image(systemSymbol: .squareAndPencilCircleFill)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(height: 20)
Text(requiredFilesText)
Spacer()
}
.padding(.vertical, 8)
.contentShape(Rectangle())
.onTapGesture {
showFileSelectionSheet = true
}
}
LocalizedPageDetailView(
isExternalPage: page.isExternalUrl,
page: page.localized(in: language),
@ -105,9 +76,6 @@ struct PageDetailView: View {
}
.padding()
}
.sheet(isPresented: $showFileSelectionSheet) {
MultiFileSelectionView(selectedFiles: $page.requiredFiles, insertSorted: true)
}
}
}

View File

@ -5,6 +5,18 @@ struct GeneralSettingsDetailView: View {
@ObservedObject
var generalSettings: GeneralSettings
@State
private var showFileSelectionSheet = false
private var requiredFilesText: String {
let count = generalSettings.requiredFiles.count
switch count {
case 0: return "No files"
case 1: return "1 file"
default: return "\(count) files"
}
}
var body: some View {
ScrollView {
VStack(alignment: .leading) {
@ -19,7 +31,7 @@ struct GeneralSettingsDetailView: View {
footer: "The maximum width of a link preview image")
IntegerPropertyView(
title: "Link Preview Image Height",
title: "Linfk Preview Image Height",
value: $generalSettings.linkPreviewImageHeight,
footer: "The maximum height of a link preview image")
@ -47,8 +59,29 @@ struct GeneralSettingsDetailView: View {
title: "Push Notification Access Token",
text: $generalSettings.pushNotificationAccessToken,
footer: "The access token to use for sending push notifications")
GenericPropertyView(
title: "Required files",
footer: "The additional files required by the page") {
HStack {
Image(systemSymbol: .squareAndPencilCircleFill)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(height: 20)
Text(requiredFilesText)
Spacer()
}
.padding(.vertical, 8)
.contentShape(Rectangle())
.onTapGesture {
showFileSelectionSheet = true
}
}
}
.padding()
}
.sheet(isPresented: $showFileSelectionSheet) {
MultiFileSelectionView(selectedFiles: $generalSettings.requiredFiles, insertSorted: true)
}
}
}