Add tag overview, improve assets

This commit is contained in:
Christoph Hagen
2024-12-15 21:20:12 +01:00
parent 8a3a0f1797
commit 1e67a99866
59 changed files with 1301 additions and 480 deletions

View File

@ -210,7 +210,7 @@ struct PageIssueView: View {
}
private func createPage(pageId: String) {
guard content.isValidIdForTagOrTagOrPost(pageId) else {
guard content.isValidIdForTagOrPageOrPost(pageId) else {
show(error: "Invalid page id, can't create page")
return
}
@ -245,7 +245,7 @@ struct PageIssueView: View {
}
private func createTag(tagId: String) {
guard content.isValidIdForTagOrTagOrPost(tagId) else {
guard content.isValidIdForTagOrPageOrPost(tagId) else {
show(error: "Invalid tag id, can't create tag")
return
}

View File

@ -23,7 +23,7 @@ struct GenerationContentView: View {
var body: some View {
switch selectedSection {
case .folders, .navigationBar, .postFeed:
case .folders, .navigationBar, .postFeed, .tagOverview:
generationView
case .pages:
PageSettingsContentView()

View File

@ -17,6 +17,8 @@ struct GenerationDetailView: View {
PostFeedSettingsView()
case .pages:
PageSettingsDetailView()
case .tagOverview:
TagOverviewDetailView()
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)

View File

@ -1,4 +1,5 @@
import SwiftUI
import SFSafeSymbols
struct NavigationBarSettingsView: View {
@ -9,7 +10,7 @@ struct NavigationBarSettingsView: View {
private var content: Content
@State
private var showTagPicker = false
private var showItemPicker = false
var body: some View {
ScrollView {
@ -21,14 +22,10 @@ struct NavigationBarSettingsView: View {
.foregroundStyle(.secondary)
.padding(.bottom, 30)
Text("Visible Tags")
.font(.headline)
FlowHStack {
ForEach(content.settings.navigationTags) { tag in
TagView(text: tag.localized(in: language).name)
.foregroundStyle(.white)
}
Button(action: { showTagPicker = true }) {
HStack {
Text("Links")
.font(.headline)
Button(action: { showItemPicker = true }) {
Image(systemSymbol: .squareAndPencilCircleFill)
.resizable()
.aspectRatio(1, contentMode: .fit)
@ -40,15 +37,19 @@ struct NavigationBarSettingsView: View {
}
.buttonStyle(.plain)
}
ForEach(content.settings.navigationItems) { tag in
TagView(text: tag.title(in: language))
.foregroundStyle(.white)
}
Text("Select the tags to show in the navigation bar. The number should be even.")
.foregroundStyle(.secondary)
}
}
.sheet(isPresented: $showTagPicker) {
TagSelectionView(
presented: $showTagPicker,
selected: $content.settings.navigationTags,
tags: $content.tags)
.sheet(isPresented: $showItemPicker) {
ItemSelectionView(
isPresented: $showItemPicker,
selectedItems: $content.settings.navigationItems)
}
}
}

View File

@ -11,51 +11,49 @@ struct PageSettingsDetailView: View {
var body: some View {
ScrollView {
VStack(alignment: .leading) {
Text("Page Settings")
.font(.largeTitle)
.bold()
Text("Change the way pages are displayed")
.padding(.bottom, 30)
DetailTitle(
title: "Page Settings",
text: "Change the way pages are displayed")
Text("Content Width")
.font(.headline)
IntegerField("", number: $content.settings.pages.contentWidth)
.textFieldStyle(.roundedBorder)
Text("The maximum width of the content in pages (in pixels)")
.foregroundStyle(.secondary)
.padding(.bottom)
IntegerPropertyView(
value: $content.settings.pages.contentWidth,
title: "Content Width",
footer: "The maximum width of the content in pages (in pixels)")
Text("Fullscreen Image Width")
.font(.headline)
IntegerField("", number: $content.settings.pages.largeImageWidth)
.textFieldStyle(.roundedBorder)
Text("The maximum width of images that are diplayed fullscreen")
.foregroundStyle(.secondary)
.padding(.bottom)
IntegerPropertyView(
value: $content.settings.pages.largeImageWidth,
title: "Fullscreen Image Width",
footer: "The maximum width of images that are diplayed fullscreen")
Text("Page Link Image Width")
.font(.headline)
IntegerField("", number: $content.settings.pages.pageLinkImageSize)
.textFieldStyle(.roundedBorder)
Text("The maximum width of images diplayed as thumbnails on page links")
.foregroundStyle(.secondary)
.padding(.bottom)
IntegerPropertyView(
value: $content.settings.pages.pageLinkImageSize,
title: "Page Link Image Width",
footer: "The maximum width of images diplayed as thumbnails on page links")
Text("Page URL Prefix")
.font(.headline)
TextField("", text: $content.settings.pages.pageUrlPrefix)
.textFieldStyle(.roundedBorder)
Text("The URL prefix used for the links to pages")
.foregroundStyle(.secondary)
.padding(.bottom)
FilePropertyView(
title: "Default CSS File",
description: "The CSS file containing the styling of all pages",
selectedFile: $content.settings.pages.defaultCssFile)
Text("Javascript Files Path")
.font(.headline)
TextField("", text: $content.settings.pages.javascriptFilesPath)
.textFieldStyle(.roundedBorder)
Text("The path to the javascript files in the output folder")
.foregroundStyle(.secondary)
.padding(.bottom)
FilePropertyView(
title: "Code Highlighting File",
description: "The JavaScript file to provide syntax highlighting of code blocks",
selectedFile: $content.settings.pages.codeHighlightingJsFile)
FilePropertyView(
title: "Audio Player CSS File",
description: "The CSS file to provide the style for the audio player",
selectedFile: $content.settings.pages.audioPlayerCssFile)
FilePropertyView(
title: "Audio Player JavaScript File",
description: "The CSS file to provide the functionality for the audio player",
selectedFile: $content.settings.pages.audioPlayerJsFile)
FilePropertyView(
title: "3D Model Viewer File",
description: "The JavaScript file to provide the functionality for the 3D model viewer",
selectedFile: $content.settings.pages.modelViewerJsFile)
}
}
}

View File

@ -85,6 +85,14 @@ struct PathSettingsView: View {
Text("The path in the output folder where the generated videos are stored")
.foregroundStyle(.secondary)
.padding(.bottom)
Text("Assets output folder")
.font(.headline)
TextField("", text: $content.settings.paths.assetsOutputFolderPath)
.textFieldStyle(.roundedBorder)
Text("The path in the output folder where assets are stored")
.foregroundStyle(.secondary)
.padding(.bottom)
}
}
}

View File

@ -11,32 +11,36 @@ struct PostFeedSettingsView: View {
var body: some View {
ScrollView {
VStack(alignment: .leading) {
Text("Post Feed Settings")
.font(.largeTitle)
.bold()
Text("Change the way the posts are displayed")
.foregroundStyle(.secondary)
.padding(.bottom, 30)
DetailTitle(title: "Post Feed Settings",
text: "Change the way the posts are displayed")
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)
IntegerPropertyView(
value: $content.settings.posts.contentWidth,
title: "Content Width",
footer: "The maximum width of the content the post feed (in pixels)")
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)
IntegerPropertyView(
value: $content.settings.posts.postsPerPage,
title: "Posts Per Page",
footer: "The maximum number of posts displayed on a single page")
LocalizedPostFeedSettingsView(settings: content.settings.localized(in: language))
FilePropertyView(
title: "Default CSS File",
description: "The CSS file containing the styling of all post pages",
selectedFile: $content.settings.posts.defaultCssFile)
FilePropertyView(
title: "Swiper CSS File",
description: "The CSS file containing the styling of image galleries in post feeds",
selectedFile: $content.settings.posts.swiperCssFile)
FilePropertyView(
title: "Swiper JavaScript File",
description: "The JavaScript file to load the image gallery code in post feeds",
selectedFile: $content.settings.posts.swiperJsFile)
LocalizedPostFeedSettingsView(
settings: content.settings.localized(in: language))
}
}
}

View File

@ -12,17 +12,19 @@ enum SettingsSection: String {
case pages = "Pages"
case tagOverview = "Tag Overview"
}
extension SettingsSection {
var icon: SFSymbol {
switch self {
//case .generation: return .arrowTriangle2Circlepath
case .folders: return .folder
case .navigationBar: return .menubarRectangle
case .postFeed: return .rectangleGrid1x2
case .pages: return .docRichtext
case .tagOverview: return .tag
}
}
}

View File

@ -0,0 +1,130 @@
import SwiftUI
struct TagOverviewDetailView: View {
@Environment(\.language)
private var language
@EnvironmentObject
private var content: Content
var body: some View {
ScrollView {
VStack(alignment: .leading) {
Text("Tag Overview")
.font(.largeTitle)
.bold()
Text("Configure the page showing all tags")
.foregroundStyle(.secondary)
.padding(.bottom, 30)
if let page = content.tagOverview?.localized(in: language) {
TagOverviewDetails(page: page)
} else {
Button("Create", action: createTagOverviewPage)
}
}
}
}
private func createTagOverviewPage() {
content.tagOverview = TagOverviewPage(
content: content,
german: .init(title: "Alle Tags", urlString: "alle"),
english: .init(title: "All tags", urlString: "all"))
}
}
private struct TagOverviewDetails: View {
@ObservedObject
var page: LocalizedTagOverviewPage
@EnvironmentObject
var content: Content
@State
private var showImagePicker = false
@State
private var newUrlString: String = ""
init(page: LocalizedTagOverviewPage) {
self.page = page
}
private var newUrlCanBeUpdated: Bool {
guard !newUrlString.isEmpty else { return false }
guard content.isValidIdForTagOrPageOrPost(newUrlString) else { return false }
return !content.containsTag(withUrlComponent: newUrlString)
}
var body: some View {
VStack(alignment: .leading) {
Text("Title")
.font(.headline)
TextField("", text: $page.title)
.textFieldStyle(.roundedBorder)
HStack {
Text("Page URL String")
.font(.headline)
TextField("", text: $newUrlString)
.textFieldStyle(.roundedBorder)
Button("Update", action: setNewId)
.disabled(!newUrlCanBeUpdated)
}
.padding(.bottom)
Text("Link Preview Title")
.font(.headline)
OptionalTextField("", text: $page.linkPreviewTitle,
prompt: page.title)
.textFieldStyle(.roundedBorder)
.padding(.bottom)
HStack {
Text("Link Preview Image")
.font(.headline)
IconButton(symbol: .squareAndPencilCircleFill,
size: 22,
color: .blue) {
showImagePicker = true
}
IconButton(symbol: .trashCircleFill,
size: 22,
color: .red) {
page.linkPreviewImage = nil
}.disabled(page.linkPreviewImage == nil)
}
.buttonStyle(.plain)
if let image = page.linkPreviewImage {
image.imageToDisplay
.resizable()
.aspectRatio(contentMode: .fit)
.frame(maxWidth: 400, maxHeight: 300)
.cornerRadius(8)
Text(image.id)
.font(.headline)
}
Text("Link Preview Description")
.font(.headline)
.padding(.top)
OptionalDescriptionField(text: $page.linkPreviewDescription)
.textFieldStyle(.roundedBorder)
.padding(.bottom)
}
.sheet(isPresented: $showImagePicker) {
ImagePickerView(showImagePicker: $showImagePicker) { image in
page.linkPreviewImage = image
}
}
}
private func setNewId() {
page.urlString = newUrlString
}
}