diff --git a/CHDataManagement.xcodeproj/project.pbxproj b/CHDataManagement.xcodeproj/project.pbxproj index 2d031d6..e3cc461 100644 --- a/CHDataManagement.xcodeproj/project.pbxproj +++ b/CHDataManagement.xcodeproj/project.pbxproj @@ -66,6 +66,10 @@ E25DA5732D018AA100AEF16D /* FileContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E25DA5722D018AA100AEF16D /* FileContentView.swift */; }; E25DA5752D018B6100AEF16D /* FileDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E25DA5742D018B6100AEF16D /* FileDetailView.swift */; }; E25DA5772D018B9900AEF16D /* File+Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = E25DA5762D018B9500AEF16D /* File+Mock.swift */; }; + E25DA58F2D02368D00AEF16D /* PageSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = E25DA58E2D02368A00AEF16D /* PageSettings.swift */; }; + E25DA5912D023A8400AEF16D /* IntegerField.swift in Sources */ = {isa = PBXBuildFile; fileRef = E25DA5902D023A7E00AEF16D /* IntegerField.swift */; }; + E25DA5932D023B3C00AEF16D /* PageSettingsFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = E25DA5922D023B3600AEF16D /* PageSettingsFile.swift */; }; + E25DA5952D023BD100AEF16D /* PageSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E25DA5942D023BCC00AEF16D /* PageSettingsView.swift */; }; E2A21C012CB16A820060935B /* PostView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2A21C002CB16A820060935B /* PostView.swift */; }; E2A21C032CB16C290060935B /* Environment+Language.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2A21C022CB16C220060935B /* Environment+Language.swift */; }; E2A21C052CB1766C0060935B /* LocalizedText.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2A21C042CB176670060935B /* LocalizedText.swift */; }; @@ -176,6 +180,10 @@ E25DA5722D018AA100AEF16D /* FileContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileContentView.swift; sourceTree = ""; }; E25DA5742D018B6100AEF16D /* FileDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileDetailView.swift; sourceTree = ""; }; E25DA5762D018B9500AEF16D /* File+Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "File+Mock.swift"; sourceTree = ""; }; + E25DA58E2D02368A00AEF16D /* PageSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageSettings.swift; sourceTree = ""; }; + E25DA5902D023A7E00AEF16D /* IntegerField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegerField.swift; sourceTree = ""; }; + E25DA5922D023B3600AEF16D /* PageSettingsFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageSettingsFile.swift; sourceTree = ""; }; + E25DA5942D023BCC00AEF16D /* PageSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageSettingsView.swift; sourceTree = ""; }; E2A21C002CB16A820060935B /* PostView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostView.swift; sourceTree = ""; }; E2A21C022CB16C220060935B /* Environment+Language.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Environment+Language.swift"; sourceTree = ""; }; E2A21C042CB176670060935B /* LocalizedText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalizedText.swift; sourceTree = ""; }; @@ -275,6 +283,7 @@ E25DA5392D00423F00AEF16D /* LocalizedSettingsFile.swift */, E25DA5332D0041CB00AEF16D /* NavigationBarSettingsFile.swift */, E25DA5352D0041E200AEF16D /* PostSettingsFile.swift */, + E25DA5922D023B3600AEF16D /* PageSettingsFile.swift */, E21850342CFAFA570090B18B /* SettingsFile.swift */, ); path = Settings; @@ -283,6 +292,7 @@ E25DA53B2D0042EA00AEF16D /* Settings */ = { isa = PBXGroup; children = ( + E25DA58E2D02368A00AEF16D /* PageSettings.swift */, E25DA5402D00446700AEF16D /* PostSettings.swift */, E25DA53E2D00441C00AEF16D /* NavigationBarSettings.swift */, E25DA53C2D0043E200AEF16D /* LocalizedSettings.swift */, @@ -304,6 +314,7 @@ E2A21C342CB9A3CA0060935B /* Settings */ = { isa = PBXGroup; children = ( + E25DA5942D023BCC00AEF16D /* PageSettingsView.swift */, E25DA5442D00952D00AEF16D /* SettingsSection.swift */, E25DA5422D0094A400AEF16D /* SettingsSidebar.swift */, E25DA5302D003FC000AEF16D /* SectionedSettingsView.swift */, @@ -319,6 +330,7 @@ E2A21C372CB9A4F10060935B /* Generic */ = { isa = PBXGroup; children = ( + E25DA5902D023A7E00AEF16D /* IntegerField.swift */, E218501C2CEE6CB30090B18B /* VerticalCenter.swift */, E2A37D2C2CED2EEE0000979F /* OptionalTextField.swift */, E2A21C2F2CB490F90060935B /* HorizontalCenter.swift */, @@ -631,6 +643,7 @@ E2A21C102CB18B3A0060935B /* FlowHStack.swift in Sources */, E25DA5382D00420E00AEF16D /* LocalizedPostSettingsFile.swift in Sources */, E2B85F3D2C4293F80047CD0C /* PageInFeed.swift in Sources */, + E25DA5952D023BD100AEF16D /* PageSettingsView.swift in Sources */, E21850092CEE01C30090B18B /* PagePickerView.swift in Sources */, E2A21C2A2CB2AA4F0060935B /* Post+Mock.swift in Sources */, E24252082C5168750029FF16 /* GenericMetadata+Localized.swift in Sources */, @@ -696,11 +709,14 @@ E2A21C0E2CB189DC0060935B /* Color+RGB.swift in Sources */, E25DA5152CFF00C100AEF16D /* Content+Load.swift in Sources */, E25DA5312D003FCB00AEF16D /* SectionedSettingsView.swift in Sources */, + E25DA58F2D02368D00AEF16D /* PageSettings.swift in Sources */, E25DA50D2CFD9BA200AEF16D /* PostTagAssignmentView.swift in Sources */, + E25DA5932D023B3C00AEF16D /* PageSettingsFile.swift in Sources */, E2A21C362CB9A3D70060935B /* FolderSettingsView.swift in Sources */, E2A21C012CB16A820060935B /* PostView.swift in Sources */, E2A21C052CB1766C0060935B /* LocalizedText.swift in Sources */, E25DA5362D0041EB00AEF16D /* PostSettingsFile.swift in Sources */, + E25DA5912D023A8400AEF16D /* IntegerField.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/CHDataManagement/Model/Settings/PageSettings.swift b/CHDataManagement/Model/Settings/PageSettings.swift new file mode 100644 index 0000000..c1004e0 --- /dev/null +++ b/CHDataManagement/Model/Settings/PageSettings.swift @@ -0,0 +1,17 @@ +import Foundation + +final class PageSettings: ObservableObject { + + /// The prefix of the urls for all pages + /// The full path will be `/` + @Published + var pageUrlPrefix: String + + @Published + var contentWidth: Int + + init(pageUrlPrefix: String, contentWidth: Int) { + self.pageUrlPrefix = pageUrlPrefix + self.contentWidth = contentWidth + } +} diff --git a/CHDataManagement/Model/Settings/PostSettings.swift b/CHDataManagement/Model/Settings/PostSettings.swift index c0ddc23..3b2123b 100644 --- a/CHDataManagement/Model/Settings/PostSettings.swift +++ b/CHDataManagement/Model/Settings/PostSettings.swift @@ -8,9 +8,9 @@ final class PostSettings: ObservableObject { /// The maximum width of the main content @Published - var contentWidth: CGFloat + var contentWidth: Int - init(postsPerPage: Int, contentWidth: CGFloat) { + init(postsPerPage: Int, contentWidth: Int) { self.postsPerPage = postsPerPage self.contentWidth = contentWidth } diff --git a/CHDataManagement/Model/Settings/Settings.swift b/CHDataManagement/Model/Settings/Settings.swift index a327f77..2d445a9 100644 --- a/CHDataManagement/Model/Settings/Settings.swift +++ b/CHDataManagement/Model/Settings/Settings.swift @@ -11,16 +11,20 @@ final class Settings: ObservableObject { @Published var posts: PostSettings + @Published + var pages: PageSettings + @Published var german: LocalizedSettings @Published var english: LocalizedSettings - init(outputDirectoryPath: String, navigationBar: NavigationBarSettings, posts: PostSettings, german: LocalizedSettings, english: LocalizedSettings) { + init(outputDirectoryPath: String, navigationBar: NavigationBarSettings, posts: PostSettings, pages: PageSettings, german: LocalizedSettings, english: LocalizedSettings) { self.outputDirectoryPath = outputDirectoryPath self.navigationBar = navigationBar self.posts = posts + self.pages = pages self.german = german self.english = english } diff --git a/CHDataManagement/Preview Content/WebsiteData+Mock.swift b/CHDataManagement/Preview Content/WebsiteData+Mock.swift index d8ab964..8d2d647 100644 --- a/CHDataManagement/Preview Content/WebsiteData+Mock.swift +++ b/CHDataManagement/Preview Content/WebsiteData+Mock.swift @@ -6,6 +6,7 @@ extension Settings { outputDirectoryPath: "/some/path", navigationBar: .init(iconPath: "/some/other/path", tags: []), posts: .mock, + pages: .mock, german: .german, english: .english) } @@ -17,6 +18,13 @@ extension PostSettings { } } +extension PageSettings { + + static var mock: PageSettings { + .init(pageUrlPrefix: "pages", contentWidth: 600) + } +} + extension LocalizedSettings { static var german: LocalizedSettings { diff --git a/CHDataManagement/Storage/Model/Settings/PageSettingsFile.swift b/CHDataManagement/Storage/Model/Settings/PageSettingsFile.swift new file mode 100644 index 0000000..ef9f41f --- /dev/null +++ b/CHDataManagement/Storage/Model/Settings/PageSettingsFile.swift @@ -0,0 +1,11 @@ + +struct PageSettingsFile { + + let pageUrlPrefix: String + + let contentWidth: Int +} + +extension PageSettingsFile: Codable { + +} diff --git a/CHDataManagement/Storage/Model/Settings/PostSettingsFile.swift b/CHDataManagement/Storage/Model/Settings/PostSettingsFile.swift index 5ba5203..b22b1b3 100644 --- a/CHDataManagement/Storage/Model/Settings/PostSettingsFile.swift +++ b/CHDataManagement/Storage/Model/Settings/PostSettingsFile.swift @@ -6,7 +6,7 @@ struct PostSettingsFile { let postsPerPage: Int /// The maximum width of the main content - let contentWidth: CGFloat + let contentWidth: Int } extension PostSettingsFile: Codable { } diff --git a/CHDataManagement/Storage/Model/Settings/SettingsFile.swift b/CHDataManagement/Storage/Model/Settings/SettingsFile.swift index 8afae56..e2ceb0e 100644 --- a/CHDataManagement/Storage/Model/Settings/SettingsFile.swift +++ b/CHDataManagement/Storage/Model/Settings/SettingsFile.swift @@ -9,6 +9,8 @@ struct SettingsFile { let posts: PostSettingsFile + let pages: PageSettingsFile + let german: LocalizedSettingsFile let english: LocalizedSettingsFile diff --git a/CHDataManagement/Views/Generic/IntegerField.swift b/CHDataManagement/Views/Generic/IntegerField.swift new file mode 100644 index 0000000..0d74181 --- /dev/null +++ b/CHDataManagement/Views/Generic/IntegerField.swift @@ -0,0 +1,31 @@ +import SwiftUI + +struct IntegerField: View { + + private let titleKey: LocalizedStringKey + + @Binding + private var number: Int + + @State + private var text: String = "" + + init(_ titleKey: LocalizedStringKey, number: Binding) { + self.titleKey = titleKey + self._number = number + } + + var body: some View { + TextField(titleKey, text: $text) + .onChange(of: text) { _, newValue in + if let intValue = Int(newValue) { + number = intValue + } else { + text = "\(number)" + } + } + .onAppear { + text = "\(number)" + } + } +} diff --git a/CHDataManagement/Views/Settings/FolderSettingsView.swift b/CHDataManagement/Views/Settings/FolderSettingsView.swift index 7d5f409..21dbb6f 100644 --- a/CHDataManagement/Views/Settings/FolderSettingsView.swift +++ b/CHDataManagement/Views/Settings/FolderSettingsView.swift @@ -21,7 +21,9 @@ struct FolderSettingsView: View { .font(.largeTitle) .bold() Text("Select the folders for the app to work.") + .foregroundStyle(.secondary) .padding(.bottom, 30) + Text("Content Folder") .font(.headline) .padding(.bottom, 1) @@ -29,7 +31,10 @@ struct FolderSettingsView: View { Button(action: selectContentFolder) { Text("Select folder") } - .padding(.bottom) + Text("The folder where the raw content of the website is stored") + .foregroundStyle(.secondary) + .padding(.bottom) + Text("Output Folder") .font(.headline) .padding(.bottom, 1) @@ -37,8 +42,9 @@ struct FolderSettingsView: View { Button(action: selectOutputFolder) { Text("Select folder") } - .padding(.bottom) - + Text("The folder where the generated website is stored") + .foregroundStyle(.secondary) + .padding(.bottom) } } } diff --git a/CHDataManagement/Views/Settings/GenerationSettingsView.swift b/CHDataManagement/Views/Settings/GenerationSettingsView.swift index 3a9175c..ac9588b 100644 --- a/CHDataManagement/Views/Settings/GenerationSettingsView.swift +++ b/CHDataManagement/Views/Settings/GenerationSettingsView.swift @@ -21,8 +21,9 @@ struct GenerationSettingsView: View { .font(.largeTitle) .bold() Text("Regenerate the website and monitor the output") + .foregroundStyle(.secondary) .padding(.bottom, 30) - + HStack { Button(action: generateFeed) { Text("Generate") diff --git a/CHDataManagement/Views/Settings/LocalizedPostFeedSettingsView.swift b/CHDataManagement/Views/Settings/LocalizedPostFeedSettingsView.swift index dc9fc61..0463909 100644 --- a/CHDataManagement/Views/Settings/LocalizedPostFeedSettingsView.swift +++ b/CHDataManagement/Views/Settings/LocalizedPostFeedSettingsView.swift @@ -13,14 +13,18 @@ struct LocalizedPostFeedSettingsView: View { .textFieldStyle(.roundedBorder) .frame(maxWidth: 400) Text("The title of all post feed pages.") + .foregroundStyle(.secondary) .padding(.bottom) + Text("URL prefix") .font(.headline) TextField("", text: $settings.feedUrlPrefix) .textFieldStyle(.roundedBorder) .frame(maxWidth: 400) Text("The prefix to generate the urls for all post feed pages.") + .foregroundStyle(.secondary) .padding(.bottom) + Text("Description") .font(.headline) TextEditor(text: $settings.description) @@ -33,6 +37,7 @@ struct LocalizedPostFeedSettingsView: View { .background(Color.gray.opacity(0.1)) .cornerRadius(8) Text("The description of all post feed pages.") + .foregroundStyle(.secondary) .padding(.bottom) } } diff --git a/CHDataManagement/Views/Settings/NavigationBarSettingsView.swift b/CHDataManagement/Views/Settings/NavigationBarSettingsView.swift index 0dc2991..17a098f 100644 --- a/CHDataManagement/Views/Settings/NavigationBarSettingsView.swift +++ b/CHDataManagement/Views/Settings/NavigationBarSettingsView.swift @@ -30,19 +30,25 @@ struct NavigationBarSettingsView: View { .font(.largeTitle) .bold() Text("Customize the navigation bar for all pages at the top of the website") + .foregroundStyle(.secondary) .padding(.bottom, 30) + Text("Icon Path") .font(.headline) TextField("", text: $content.settings.navigationBar.iconPath) .textFieldStyle(.roundedBorder) .frame(maxWidth: 300) Text("Specify the path to the icon file with regard to the final website folder.") + .foregroundStyle(.secondary) .padding(.bottom, 30) + Text("Icon Description") .font(.headline) IconDescriptionView(settings: content.settings.localized(in: language)) Text("Provide a description of the icon for screen readers.") - .padding(.bottom, 30) + .foregroundStyle(.secondary) + .padding(.bottom) + Text("Visible Tags") .font(.headline) FlowHStack { @@ -66,6 +72,7 @@ struct NavigationBarSettingsView: View { .buttonStyle(.plain) } Text("Select the tags to show in the navigation bar. The number should be even.") + .foregroundStyle(.secondary) } } .sheet(isPresented: $showTagPicker) { diff --git a/CHDataManagement/Views/Settings/PageSettingsView.swift b/CHDataManagement/Views/Settings/PageSettingsView.swift new file mode 100644 index 0000000..f061f78 --- /dev/null +++ b/CHDataManagement/Views/Settings/PageSettingsView.swift @@ -0,0 +1,47 @@ +import SwiftUI + +struct PageSettingsView: View { + + @Environment(\.language) + private var language + + @EnvironmentObject + private var content: Content + + var body: some View { + ScrollView { + VStack(alignment: .leading) { + Text("Page Settings") + .font(.largeTitle) + .bold() + Text("Change the way pages are displayed") + .padding(.bottom, 30) + + Text("Content Width") + .font(.headline) + IntegerField("", number: $content.settings.pages.contentWidth) + .textFieldStyle(.roundedBorder) + .frame(maxWidth: 400) + Text("The maximum width of the content in pages (in pixels)") + .foregroundStyle(.secondary) + .padding(.bottom) + + Text("Page URL Prefix") + .font(.headline) + TextField("", text: $content.settings.pages.pageUrlPrefix) + .textFieldStyle(.roundedBorder) + .frame(maxWidth: 400) + Text("The URL prefix used for the links to pages") + .foregroundStyle(.secondary) + .padding(.bottom) + } + } + } +} + + +#Preview { + PageSettingsView() + .environmentObject(Content.mock) + .padding() +} diff --git a/CHDataManagement/Views/Settings/PostFeedSettingsView.swift b/CHDataManagement/Views/Settings/PostFeedSettingsView.swift index b1abf3b..971ecb0 100644 --- a/CHDataManagement/Views/Settings/PostFeedSettingsView.swift +++ b/CHDataManagement/Views/Settings/PostFeedSettingsView.swift @@ -15,7 +15,27 @@ struct PostFeedSettingsView: View { .font(.largeTitle) .bold() Text("Change the way the posts are displayed") + .foregroundStyle(.secondary) .padding(.bottom, 30) + + Text("Content Width") + .font(.headline) + IntegerField("", number: $content.settings.posts.contentWidth) + .textFieldStyle(.roundedBorder) + .frame(maxWidth: 400) + Text("The maximum width of the content the post feed (in pixels)") + .foregroundStyle(.secondary) + .padding(.bottom) + + Text("Posts Per Page") + .font(.headline) + IntegerField("", number: $content.settings.posts.postsPerPage) + .textFieldStyle(.roundedBorder) + .frame(maxWidth: 400) + Text("The maximum number of posts displayed on a single page") + .foregroundStyle(.secondary) + .padding(.bottom) + LocalizedPostFeedSettingsView(settings: content.settings.localized(in: language).posts) } } diff --git a/CHDataManagement/Views/Settings/SectionedSettingsView.swift b/CHDataManagement/Views/Settings/SectionedSettingsView.swift index 6e6fcc3..8c9265b 100644 --- a/CHDataManagement/Views/Settings/SectionedSettingsView.swift +++ b/CHDataManagement/Views/Settings/SectionedSettingsView.swift @@ -31,6 +31,8 @@ struct DetailView: View { NavigationBarSettingsView() case .postFeed: PostFeedSettingsView() + case .pages: + PageSettingsView() case .none: Text("Select a setting from the sidebar") .foregroundStyle(.secondary) @@ -42,40 +44,6 @@ struct DetailView: View { } } - -struct AppearanceView: View { - var body: some View { - VStack(alignment: .leading) { - Text("Appearance Settings") - .font(.largeTitle) - .bold() - Text("Customize the look and feel of the app.") - } - } -} - -struct NotificationsView: View { - var body: some View { - VStack(alignment: .leading) { - Text("Notifications Settings") - .font(.largeTitle) - .bold() - Text("Manage your notification preferences.") - } - } -} - -struct PrivacyView: View { - var body: some View { - VStack(alignment: .leading) { - Text("Privacy Settings") - .font(.largeTitle) - .bold() - Text("Configure your privacy and security settings.") - } - } -} - #Preview { SectionedSettingsView() } diff --git a/CHDataManagement/Views/Settings/SettingsSection.swift b/CHDataManagement/Views/Settings/SettingsSection.swift index d0b0626..b88cccd 100644 --- a/CHDataManagement/Views/Settings/SettingsSection.swift +++ b/CHDataManagement/Views/Settings/SettingsSection.swift @@ -10,6 +10,8 @@ enum SettingsSection: String { case postFeed = "Post Feed" + case pages = "Pages" + } extension SettingsSection { @@ -20,6 +22,7 @@ extension SettingsSection { case .folders: return .folder case .navigationBar: return .menubarRectangle case .postFeed: return .rectangleGrid1x2 + case .pages: return .docRichtext } } }