diff --git a/CHDataManagement.xcodeproj/project.pbxproj b/CHDataManagement.xcodeproj/project.pbxproj index 0560a93..6a2f796 100644 --- a/CHDataManagement.xcodeproj/project.pbxproj +++ b/CHDataManagement.xcodeproj/project.pbxproj @@ -127,7 +127,7 @@ E29D317D2D086AB00051B7F4 /* Int+Random.swift in Sources */ = {isa = PBXBuildFile; fileRef = E29D317C2D086AAE0051B7F4 /* Int+Random.swift */; }; E29D317F2D086F4C0051B7F4 /* StatisticsIcons.swift in Sources */ = {isa = PBXBuildFile; fileRef = E29D317E2D086F490051B7F4 /* StatisticsIcons.swift */; }; E29D31832D0A43DB0051B7F4 /* RelatedPageLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = E29D31822D0A43D60051B7F4 /* RelatedPageLink.swift */; }; - E29D31852D0AE8EE0051B7F4 /* RequiredHeaders.swift in Sources */ = {isa = PBXBuildFile; fileRef = E29D31842D0AE8EE0051B7F4 /* RequiredHeaders.swift */; }; + E29D31852D0AE8EE0051B7F4 /* KnownHeaderElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = E29D31842D0AE8EE0051B7F4 /* KnownHeaderElement.swift */; }; E29D31892D0AED1F0051B7F4 /* ModelViewer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E29D31882D0AED1B0051B7F4 /* ModelViewer.swift */; }; E29D318B2D0B07EE0051B7F4 /* ContentBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = E29D318A2D0B07E60051B7F4 /* ContentBox.swift */; }; E29D318E2D0B2E680051B7F4 /* PageSettingsContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E29D318D2D0B2E640051B7F4 /* PageSettingsContentView.swift */; }; @@ -311,7 +311,7 @@ E29D317C2D086AAE0051B7F4 /* Int+Random.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Int+Random.swift"; sourceTree = ""; }; E29D317E2D086F490051B7F4 /* StatisticsIcons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatisticsIcons.swift; sourceTree = ""; }; E29D31822D0A43D60051B7F4 /* RelatedPageLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelatedPageLink.swift; sourceTree = ""; }; - E29D31842D0AE8EE0051B7F4 /* RequiredHeaders.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequiredHeaders.swift; sourceTree = ""; }; + E29D31842D0AE8EE0051B7F4 /* KnownHeaderElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnownHeaderElement.swift; sourceTree = ""; }; E29D31882D0AED1B0051B7F4 /* ModelViewer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModelViewer.swift; sourceTree = ""; }; E29D318A2D0B07E60051B7F4 /* ContentBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentBox.swift; sourceTree = ""; }; E29D318D2D0B2E640051B7F4 /* PageSettingsContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageSettingsContentView.swift; sourceTree = ""; }; @@ -452,7 +452,7 @@ E22990232D0EDBD0009F8D77 /* HeaderElement.swift */, E29D31B62D0DAC030051B7F4 /* Page Content */, E29D318F2D0B34870051B7F4 /* PageContentAnomaly.swift */, - E29D31842D0AE8EE0051B7F4 /* RequiredHeaders.swift */, + E29D31842D0AE8EE0051B7F4 /* KnownHeaderElement.swift */, E25DA5222CFF6C2600AEF16D /* ImageGenerator.swift */, E218502E2CFAF6990090B18B /* LocalizedWebsiteGenerator.swift */, E25DA5792D01C63E00AEF16D /* PageContentGenerator.swift */, @@ -921,7 +921,7 @@ E242520A2C52C9260029FF16 /* ContentLanguage.swift in Sources */, E2B85F452C429ED60047CD0C /* ImageGallery.swift in Sources */, E2B85F3B2C428F0E0047CD0C /* Post.swift in Sources */, - E29D31852D0AE8EE0051B7F4 /* RequiredHeaders.swift in Sources */, + E29D31852D0AE8EE0051B7F4 /* KnownHeaderElement.swift in Sources */, E25DA51B2CFF08BB00AEF16D /* PostFeedPageNavigation.swift in Sources */, E29D317F2D086F4C0051B7F4 /* StatisticsIcons.swift in Sources */, E2A21C082CB17B870060935B /* TagView.swift in Sources */, diff --git a/CHDataManagement/Generator/FeedPageGenerator.swift b/CHDataManagement/Generator/FeedPageGenerator.swift index c04130e..229b71c 100644 --- a/CHDataManagement/Generator/FeedPageGenerator.swift +++ b/CHDataManagement/Generator/FeedPageGenerator.swift @@ -8,27 +8,12 @@ final class FeedPageGenerator { self.content = content } - var swiperIncludes: [HeaderElement] { - var result = [HeaderElement]() + private func includeSwiper(in headers: inout Set) { if let swiperCss = content.settings.posts.swiperCssFile { - result.append(.css(swiperCss)) - } else { - #warning("Add warning message") + headers.insert(.css(file: swiperCss, order: HeaderElement.swiperCssFileOrder)) } if let swiperJs = content.settings.posts.swiperJsFile { - result.append(.js(file: swiperJs, defer: true)) - } else { - #warning("Add warning message") - } - return result - } - - var defaultHeaders: [HeaderElement] { - if let header = content.settings.posts.defaultCssFile { - return [.css(header)] - } else { - #warning("Add warning message") - return [] + headers.insert(.js(file: swiperJs, defer: true)) } } @@ -39,10 +24,11 @@ final class FeedPageGenerator { showTitle: Bool, pageNumber: Int, totalPages: Int) -> String { - var headers = defaultHeaders + var headers = content.defaultPageHeaders var footer = "" if posts.contains(where: { $0.images.count > 1 }) { - headers += swiperIncludes + // Sort swiper style sheet before default style sheet + includeSwiper(in: &headers) footer = swiperInitScript(posts: posts) } @@ -68,15 +54,14 @@ final class FeedPageGenerator { } func swiperInitScript(posts: [FeedEntryData]) -> String { - var result = "" + result += "}; " return result - } } diff --git a/CHDataManagement/Generator/HeaderElement.swift b/CHDataManagement/Generator/HeaderElement.swift index c00bf6c..18b80b9 100644 --- a/CHDataManagement/Generator/HeaderElement.swift +++ b/CHDataManagement/Generator/HeaderElement.swift @@ -1,33 +1,135 @@ +#warning("Add remaining header elements") +// +// +// + +// TODO: Move to settings? +extension HeaderElement { + + static let swiperCssFileOrder = 41 + + static let defaultCssFileOrder = 42 + + static let audioPlayerCssOrder = 43 +} + enum HeaderElement { - case css(FileResource) + + /// Order: 10-19 + case icon(file: FileResource, size: Int, rel: String) + + /// Order: From 40-99, lower numbers appear first + case css(file: FileResource, order: Int) + + /// Order: 20-29 case js(file: FileResource, defer: Bool) + + /// Order: 30-39 case jsModule(FileResource) + + case author(String) + case title(String) + case description(String) + case charset + case viewport + + case robots + + var order: Int { + switch self { + case .charset: + return 1 + case .robots: + return 2 + case .viewport: + return 3 + case .icon: + return 10 + case .css(_, let order): + return order + case .js: + return 20 + case .jsModule: + return 30 + case .author: + return 100 + case .title: + return 101 + case .description: + return 102 + } + } +} + +extension HeaderElement: Hashable { + +} + +extension HeaderElement: Comparable { + + static func < (lhs: HeaderElement, rhs: HeaderElement) -> Bool { + lhs.order < rhs.order + } } extension HeaderElement { var content: String { switch self { - case .css(let file): + case .icon(let file, let size, let rel): + return "" + case .css(let file, _): return "" case .js(let file, let deferred): let deferText = deferred ? " defer" : "" return "" case .jsModule(let file): return "" + case .author(let author): + return "" case .title(let title): return "\(title)" case .description(let description): - return "" + return "" case .charset: return "" case .viewport: return "" + case .robots: + return "" + } + } +} + +extension HeaderElement: CustomStringConvertible { + + var description: String { + switch self { + case .icon(let file, _, _): + return file.description + case .css(let file, _): + return file.description + case .js(let file, let deferred): + return file.description + (deferred ? " (deferred)" : "") + case .jsModule(let file): + return file.description + case .author: + return "author" + case .title: + return "title" + case .description: + return "description" + case .charset: + return "charset" + case .viewport: + return "viewport" + case .robots: + return "robots" } } } diff --git a/CHDataManagement/Generator/RequiredHeaders.swift b/CHDataManagement/Generator/KnownHeaderElement.swift similarity index 61% rename from CHDataManagement/Generator/RequiredHeaders.swift rename to CHDataManagement/Generator/KnownHeaderElement.swift index b3c291a..c5f4917 100644 --- a/CHDataManagement/Generator/RequiredHeaders.swift +++ b/CHDataManagement/Generator/KnownHeaderElement.swift @@ -1,5 +1,5 @@ -enum HeaderFile: Int { +enum KnownHeaderElement: Int { case codeHightlighting = 4 @@ -23,7 +23,7 @@ enum HeaderFile: Int { } case .audioPlayerCss: if let file = content.settings.pages.audioPlayerCssFile { - return .css(file) + return .css(file: file, order: HeaderElement.audioPlayerCssOrder) } case .audioPlayerJs: if let file = content.settings.pages.audioPlayerJsFile { @@ -34,13 +34,27 @@ enum HeaderFile: Int { } } -extension HeaderFile: Comparable { +extension KnownHeaderElement: Comparable { - static func < (lhs: HeaderFile, rhs: HeaderFile) -> Bool { + static func < (lhs: KnownHeaderElement, rhs: KnownHeaderElement) -> Bool { lhs.rawValue < rhs.rawValue } } -typealias RequiredHeaders = Set +extension KnownHeaderElement: CustomStringConvertible { + + var description: String { + switch self { + case .codeHightlighting: + return "code-highlighting" + case .modelViewer: + return "model-viewer" + case .audioPlayerCss: + return "audio-player-css" + case .audioPlayerJs: + return "audio-player-js" + } + } +} diff --git a/CHDataManagement/Generator/LocalizedWebsiteGenerator.swift b/CHDataManagement/Generator/LocalizedWebsiteGenerator.swift index 89ffef1..631d2ea 100644 --- a/CHDataManagement/Generator/LocalizedWebsiteGenerator.swift +++ b/CHDataManagement/Generator/LocalizedWebsiteGenerator.swift @@ -2,10 +2,23 @@ import Foundation final class LocalizedWebsiteGenerator { + private let content: Content + let language: ContentLanguage + private let imageGenerator: ImageGenerator + private let localizedPostSettings: LocalizedPostSettings + init(content: Content, language: ContentLanguage) { + self.language = language + self.content = content + self.localizedPostSettings = content.settings.localized(in: language) + self.imageGenerator = ImageGenerator( + storage: content.storage, + relativeImageOutputPath: content.settings.paths.imagesOutputFolderPath) + } + private var outputDirectory: URL { content.settings.outputDirectory } @@ -18,19 +31,6 @@ final class LocalizedWebsiteGenerator { CGFloat(content.settings.posts.contentWidth) } - private let content: Content - - private let imageGenerator: ImageGenerator - - init(content: Content, language: ContentLanguage) { - self.language = language - self.content = content - self.localizedPostSettings = content.settings.localized(in: language) - self.imageGenerator = ImageGenerator( - storage: content.storage, - relativeImageOutputPath: content.settings.paths.imagesOutputFolderPath) - } - func generateWebsite(callback: (String) -> Void) -> Bool { guard imageGenerator.prepareForGeneration() else { return false diff --git a/CHDataManagement/Generator/PageGenerationResults.swift b/CHDataManagement/Generator/PageGenerationResults.swift index 4a2eff1..e73b8ae 100644 --- a/CHDataManagement/Generator/PageGenerationResults.swift +++ b/CHDataManagement/Generator/PageGenerationResults.swift @@ -45,7 +45,7 @@ final class PageGenerationResults: ObservableObject { var invalidCommands: [(command: ShorthandMarkdownKey?, markdown: String)] = [] @Published - var requiredHeaders: RequiredHeaders = [] + var requiredHeaders: Set = [] @Published var requiredFooters: Set = [] diff --git a/CHDataManagement/Generator/PageGenerator.swift b/CHDataManagement/Generator/PageGenerator.swift index a08fc47..b227060 100644 --- a/CHDataManagement/Generator/PageGenerator.swift +++ b/CHDataManagement/Generator/PageGenerator.swift @@ -9,14 +9,15 @@ final class PageGenerator { self.imageGenerator = imageGenerator } - func makeHeaders(requiredItems: [HeaderFile]) -> [HeaderElement] { - var result = [HeaderElement]() + private func makeHeaders(requiredItems: Set) -> Set { + var result = content.defaultPageHeaders for item in requiredItems { guard let header = item.header(content: content) else { + print("Missing header \(item)") #warning("Add warning on missing file assignment") continue } - result.append(header) + result.insert(header) } return result } @@ -39,7 +40,8 @@ final class PageGenerator { url: content.absoluteUrlToTag(tag, language: language)) } - let headers = makeHeaders(requiredItems: contentGenerator.results.requiredHeaders.sorted()) + let headers = makeHeaders(requiredItems: contentGenerator.results.requiredHeaders) + print("Headers for page: \(headers)") let fullPage = ContentPage( language: language, diff --git a/CHDataManagement/Main/MainView.swift b/CHDataManagement/Main/MainView.swift index 6d7156d..758ce13 100644 --- a/CHDataManagement/Main/MainView.swift +++ b/CHDataManagement/Main/MainView.swift @@ -16,6 +16,7 @@ import SFSafeSymbols #warning("Generate pages for posts") #warning("Clean up mock content") #warning("Show posts linking to a page") +#warning("Add author to settings and page headers") @main struct MainView: App { diff --git a/CHDataManagement/Model/Content+Generation.swift b/CHDataManagement/Model/Content+Generation.swift index 3e1a12b..dc20a64 100644 --- a/CHDataManagement/Model/Content+Generation.swift +++ b/CHDataManagement/Model/Content+Generation.swift @@ -1,5 +1,54 @@ +import Foundation + extension Content { + func generatePage(_ page: Page) -> Bool { + guard startGenerating() else { return false } + defer { endGenerating() } + + for language in ContentLanguage.allCases { + guard generateInternal(page, in: language) else { + return false + } + } + return true + } + + func generatePage(_ page: Page, in language: ContentLanguage) -> Bool { + guard startGenerating() else { return false } + defer { endGenerating() } + return generateInternal(page, in: language) + } + + private func startGenerating() -> Bool { + guard !isGeneratingWebsite else { + return false + } + // TODO: Fix bug where multiple generating operations can be started + // due to dispatch of locking property on main queue + DispatchQueue.main.async { + self.isGeneratingWebsite = true + } + return true + } + + private func endGenerating() { + DispatchQueue.main.async { + self.isGeneratingWebsite = false + } + } + + private func generateInternal(_ page: Page, in language: ContentLanguage) -> Bool { + let generator = LocalizedWebsiteGenerator( + content: self, + language: language) + if !generator.generate(page: page) { + print("Generation failed") + return false + } + return true + } + private func makeCleanAbsolutePath(_ path: String) -> String { ("/" + path).replacingOccurrences(of: "//", with: "/") } @@ -36,10 +85,20 @@ extension Content { tags.first { $0.id == tagId } } + // MARK: Generation input + func navigationBar(in language: ContentLanguage) -> [NavigationBar.Link] { settings.navigationItems.map { .init(text: $0.title(in: language), url: $0.absoluteUrl(in: language)) } } + + var defaultPageHeaders: Set { + var result: Set = [.charset, .viewport] + if let defaultCss = settings.posts.defaultCssFile { + result.insert(.css(file: defaultCss, order: HeaderElement.defaultCssFileOrder)) + } + return result + } } diff --git a/CHDataManagement/Model/Content.swift b/CHDataManagement/Model/Content.swift index 9ee9fb9..6c71852 100644 --- a/CHDataManagement/Model/Content.swift +++ b/CHDataManagement/Model/Content.swift @@ -25,6 +25,9 @@ final class Content: ObservableObject { @Published var results: [ItemId : PageGenerationResults] = [:] + @Published + var isGeneratingWebsite = false + @AppStorage("contentPath") private var storedContentPath: String = "" diff --git a/CHDataManagement/Model/FileResource.swift b/CHDataManagement/Model/FileResource.swift index 3605e2a..7735a5f 100644 --- a/CHDataManagement/Model/FileResource.swift +++ b/CHDataManagement/Model/FileResource.swift @@ -137,3 +137,10 @@ final class FileResource: Item { extension FileResource: LocalizedItem { } + +extension FileResource: CustomStringConvertible { + + var description: String { + id + } +} diff --git a/CHDataManagement/Model/Settings/PageSettings.swift b/CHDataManagement/Model/Settings/PageSettings.swift index 2aa6f24..f7da147 100644 --- a/CHDataManagement/Model/Settings/PageSettings.swift +++ b/CHDataManagement/Model/Settings/PageSettings.swift @@ -44,7 +44,7 @@ final class PageSettings: ObservableObject { defaultCssFile: defaultCssFile?.id, codeHighlightingJsFile: codeHighlightingJsFile?.id, audioPlayerJsFile: audioPlayerJsFile?.id, - audioPlayerCssFile: audioPlayerJsFile?.id, + audioPlayerCssFile: audioPlayerCssFile?.id, modelViewerJsFile: modelViewerJsFile?.id) } } diff --git a/CHDataManagement/Page Elements/ContentElements/AudioPlayer/AudioPlayerContent.swift b/CHDataManagement/Page Elements/ContentElements/AudioPlayer/AudioPlayerContent.swift index 6983243..7ff3347 100644 --- a/CHDataManagement/Page Elements/ContentElements/AudioPlayer/AudioPlayerContent.swift +++ b/CHDataManagement/Page Elements/ContentElements/AudioPlayer/AudioPlayerContent.swift @@ -18,11 +18,11 @@ struct AudioPlayerScript: HtmlProducer { } func populate(_ result: inout String) { - result += "" diff --git a/CHDataManagement/Pages/ContentPage.swift b/CHDataManagement/Pages/ContentPage.swift index 59d3df5..14f665d 100644 --- a/CHDataManagement/Pages/ContentPage.swift +++ b/CHDataManagement/Pages/ContentPage.swift @@ -24,7 +24,7 @@ struct ContentPage: HtmlProducer { private let icons: Set - init(language: ContentLanguage, dateString: String, title: String, tags: [FeedEntryData.Tag], linkTitle: String, description: String, navigationBarLinks: [NavigationBar.Link], pageContent: String, headers: [HeaderElement], footers: [String], icons: Set) { + init(language: ContentLanguage, dateString: String, title: String, tags: [FeedEntryData.Tag], linkTitle: String, description: String, navigationBarLinks: [NavigationBar.Link], pageContent: String, headers: Set, footers: [String], icons: Set) { self.language = language self.dateString = dateString self.title = title @@ -33,7 +33,7 @@ struct ContentPage: HtmlProducer { self.description = description self.navigationBarLinks = navigationBarLinks self.pageContent = pageContent - self.headers = headers + self.headers = headers.union([.title(title), .description(description)]).sorted() self.footers = footers.joined() self.icons = icons } @@ -41,7 +41,7 @@ struct ContentPage: HtmlProducer { func populate(_ result: inout String) { // TODO: Add headers and footers from page content result += "" - result += PageHead(items: [.charset, .viewport] + headers).content + result += PageHead(items: headers).content result += "" result += NavigationBar(links: navigationBarLinks).content diff --git a/CHDataManagement/Pages/GenericPage.swift b/CHDataManagement/Pages/GenericPage.swift index a0100df..ad8bc3c 100644 --- a/CHDataManagement/Pages/GenericPage.swift +++ b/CHDataManagement/Pages/GenericPage.swift @@ -16,19 +16,21 @@ struct GenericPage { let insertedContent: (inout String) -> Void - init(language: ContentLanguage, title: String, description: String, links: [NavigationBar.Link], headers: [HeaderElement], additionalFooter: String, insertedContent: @escaping (inout String) -> Void) { + init(language: ContentLanguage, title: String, description: String, links: [NavigationBar.Link], headers: Set, additionalFooter: String, insertedContent: @escaping (inout String) -> Void) { self.language = language self.title = title self.description = description self.links = links - self.headers = headers + self.headers = headers.union([.title(title), .description(description)]).sorted() self.additionalFooter = additionalFooter self.insertedContent = insertedContent } + var content: String { +#warning("Consolidate this code with ContentPage") var result = "" result += "" - result += PageHead(items: [.charset, .viewport] + headers).content + result += PageHead(items: headers).content result += "" result += NavigationBar(links: links).content result += "
" diff --git a/CHDataManagement/Views/Generic/FilePropertyView.swift b/CHDataManagement/Views/Generic/FilePropertyView.swift index f463f8e..9d3725a 100644 --- a/CHDataManagement/Views/Generic/FilePropertyView.swift +++ b/CHDataManagement/Views/Generic/FilePropertyView.swift @@ -9,6 +9,15 @@ struct FilePropertyView: View { @Binding var selectedFile: FileResource? + let allowedType: FileFilterType? + + init(title: LocalizedStringKey, footer: LocalizedStringKey, selectedFile: Binding, allowedType: FileFilterType? = nil) { + self.title = title + self.footer = footer + self._selectedFile = selectedFile + self.allowedType = allowedType + } + @State private var showFileSelectionSheet = false @@ -23,7 +32,7 @@ struct FilePropertyView: View { } } .sheet(isPresented: $showFileSelectionSheet) { - FileSelectionView(selectedFile: $selectedFile) + FileSelectionView(selectedFile: $selectedFile, allowedType: allowedType) } } } diff --git a/CHDataManagement/Views/Pages/PageDetailView.swift b/CHDataManagement/Views/Pages/PageDetailView.swift index 0e6da23..2c8e2ec 100644 --- a/CHDataManagement/Views/Pages/PageDetailView.swift +++ b/CHDataManagement/Views/Pages/PageDetailView.swift @@ -12,9 +12,6 @@ struct PageDetailView: View { @ObservedObject private var page: Page - @State - private var isGeneratingWebsite = false - @State private var didGenerateWebsite: Bool? @@ -28,11 +25,11 @@ struct PageDetailView: View { DetailTitle( title: "Page", text: "A page contains longer content") - HStack { + HStack(alignment: .firstTextBaseline) { Button(action: generate) { Text("Generate") } - .disabled(isGeneratingWebsite) + .disabled(content.isGeneratingWebsite) if let didGenerateWebsite { if didGenerateWebsite { Image(systemSymbol: .checkmarkCircleFill) @@ -93,20 +90,9 @@ struct PageDetailView: View { print("Missing output folder") return } - isGeneratingWebsite = true DispatchQueue.global(qos: .userInitiated).async { - var success = true - for language in ContentLanguage.allCases { - let generator = LocalizedWebsiteGenerator( - content: content, - language: language) - if !generator.generate(page: page) { - print("Generation failed") - success = false - } - } + let success = content.generatePage(page) DispatchQueue.main.async { - isGeneratingWebsite = false didGenerateWebsite = success } } diff --git a/CHDataManagement/Views/Settings/NavigationBarSettingsView.swift b/CHDataManagement/Views/Settings/NavigationBarSettingsView.swift index c85f696..0b99b53 100644 --- a/CHDataManagement/Views/Settings/NavigationBarSettingsView.swift +++ b/CHDataManagement/Views/Settings/NavigationBarSettingsView.swift @@ -42,6 +42,7 @@ struct NavigationBarSettingsView: View { Text("Select the tags to show in the navigation bar. The number should be even.") .foregroundStyle(.secondary) } + .padding() } .sheet(isPresented: $showItemPicker) { ItemSelectionView( diff --git a/CHDataManagement/Views/Settings/PageSettingsDetailView.swift b/CHDataManagement/Views/Settings/PageSettingsDetailView.swift index 17bf64b..106baf5 100644 --- a/CHDataManagement/Views/Settings/PageSettingsDetailView.swift +++ b/CHDataManagement/Views/Settings/PageSettingsDetailView.swift @@ -33,28 +33,34 @@ struct PageSettingsDetailView: View { FilePropertyView( title: "Default CSS File", footer: "The CSS file containing the styling of all pages", - selectedFile: $content.settings.pages.defaultCssFile) + selectedFile: $content.settings.pages.defaultCssFile, + allowedType: .text) FilePropertyView( title: "Code Highlighting File", footer: "The JavaScript file to provide syntax highlighting of code blocks", - selectedFile: $content.settings.pages.codeHighlightingJsFile) + selectedFile: $content.settings.pages.codeHighlightingJsFile, + allowedType: .text) FilePropertyView( title: "Audio Player CSS File", footer: "The CSS file to provide the style for the audio player", - selectedFile: $content.settings.pages.audioPlayerCssFile) + selectedFile: $content.settings.pages.audioPlayerCssFile, + allowedType: .text) FilePropertyView( title: "Audio Player JavaScript File", footer: "The CSS file to provide the functionality for the audio player", - selectedFile: $content.settings.pages.audioPlayerJsFile) + selectedFile: $content.settings.pages.audioPlayerJsFile, + allowedType: .text) FilePropertyView( title: "3D Model Viewer File", footer: "The JavaScript file to provide the functionality for the 3D model viewer", - selectedFile: $content.settings.pages.modelViewerJsFile) + selectedFile: $content.settings.pages.modelViewerJsFile, + allowedType: .text) } + .padding() } } } diff --git a/CHDataManagement/Views/Settings/PostFeedSettingsView.swift b/CHDataManagement/Views/Settings/PostFeedSettingsView.swift index 095e007..90212c1 100644 --- a/CHDataManagement/Views/Settings/PostFeedSettingsView.swift +++ b/CHDataManagement/Views/Settings/PostFeedSettingsView.swift @@ -42,6 +42,7 @@ struct PostFeedSettingsView: View { LocalizedPostFeedSettingsView( settings: content.settings.localized(in: language)) } + .padding() } } } diff --git a/CHDataManagement/Views/Settings/TagOverviewDetailView.swift b/CHDataManagement/Views/Settings/TagOverviewDetailView.swift index bc52e74..2d32b23 100644 --- a/CHDataManagement/Views/Settings/TagOverviewDetailView.swift +++ b/CHDataManagement/Views/Settings/TagOverviewDetailView.swift @@ -70,5 +70,6 @@ private struct TagOverviewDetails: View { text: $page.linkPreviewDescription, footer: "The description to show in previews of the page") } + .padding() } }