Add page settings, improve settings UI
This commit is contained in:
parent
f2d78aef93
commit
18eb64f289
@ -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 = "<group>"; };
|
||||
E25DA5742D018B6100AEF16D /* FileDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileDetailView.swift; sourceTree = "<group>"; };
|
||||
E25DA5762D018B9500AEF16D /* File+Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "File+Mock.swift"; sourceTree = "<group>"; };
|
||||
E25DA58E2D02368A00AEF16D /* PageSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageSettings.swift; sourceTree = "<group>"; };
|
||||
E25DA5902D023A7E00AEF16D /* IntegerField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegerField.swift; sourceTree = "<group>"; };
|
||||
E25DA5922D023B3600AEF16D /* PageSettingsFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageSettingsFile.swift; sourceTree = "<group>"; };
|
||||
E25DA5942D023BCC00AEF16D /* PageSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageSettingsView.swift; sourceTree = "<group>"; };
|
||||
E2A21C002CB16A820060935B /* PostView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostView.swift; sourceTree = "<group>"; };
|
||||
E2A21C022CB16C220060935B /* Environment+Language.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Environment+Language.swift"; sourceTree = "<group>"; };
|
||||
E2A21C042CB176670060935B /* LocalizedText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalizedText.swift; sourceTree = "<group>"; };
|
||||
@ -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;
|
||||
};
|
||||
|
17
CHDataManagement/Model/Settings/PageSettings.swift
Normal file
17
CHDataManagement/Model/Settings/PageSettings.swift
Normal file
@ -0,0 +1,17 @@
|
||||
import Foundation
|
||||
|
||||
final class PageSettings: ObservableObject {
|
||||
|
||||
/// The prefix of the urls for all pages
|
||||
/// The full path will be `<pagePrefix>/<page-url-component>`
|
||||
@Published
|
||||
var pageUrlPrefix: String
|
||||
|
||||
@Published
|
||||
var contentWidth: Int
|
||||
|
||||
init(pageUrlPrefix: String, contentWidth: Int) {
|
||||
self.pageUrlPrefix = pageUrlPrefix
|
||||
self.contentWidth = contentWidth
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -0,0 +1,11 @@
|
||||
|
||||
struct PageSettingsFile {
|
||||
|
||||
let pageUrlPrefix: String
|
||||
|
||||
let contentWidth: Int
|
||||
}
|
||||
|
||||
extension PageSettingsFile: Codable {
|
||||
|
||||
}
|
@ -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 { }
|
||||
|
@ -9,6 +9,8 @@ struct SettingsFile {
|
||||
|
||||
let posts: PostSettingsFile
|
||||
|
||||
let pages: PageSettingsFile
|
||||
|
||||
let german: LocalizedSettingsFile
|
||||
|
||||
let english: LocalizedSettingsFile
|
||||
|
31
CHDataManagement/Views/Generic/IntegerField.swift
Normal file
31
CHDataManagement/Views/Generic/IntegerField.swift
Normal file
@ -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<Int>) {
|
||||
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)"
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
47
CHDataManagement/Views/Settings/PageSettingsView.swift
Normal file
47
CHDataManagement/Views/Settings/PageSettingsView.swift
Normal file
@ -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()
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user