Rework content commands, add audio player

This commit is contained in:
Christoph Hagen
2024-12-14 16:31:40 +01:00
parent b3b8c9a610
commit be2aab2ea8
52 changed files with 1758 additions and 767 deletions

View File

@ -69,6 +69,7 @@ struct AddPageView: View {
let page = Page(
content: content,
id: newPageId,
externalLink: nil,
isDraft: true,
createdDate: .now,
startDate: .now,

View File

@ -6,18 +6,14 @@ struct LocalizedPageContentView: View {
let pageId: String
let language: ContentLanguage
@ObservedObject
var page: LocalizedPage
@Environment(\.language)
private var language
@State
private var isGeneratingWebsite = false
@State
private var loadedPageContentLanguage: ContentLanguage?
@State
private var pageContent: String = ""
@ -27,10 +23,13 @@ struct LocalizedPageContentView: View {
@State
private var generationResults = PageGenerationResults()
@State
private var didChangeContent = false
init(pageId: String, page: LocalizedPage) {
init(pageId: String, page: LocalizedPage, language: ContentLanguage) {
self.pageId = pageId
self.page = page
self.language = language
}
var body: some View {
@ -55,6 +54,9 @@ struct LocalizedPageContentView: View {
HighlightedTextEditor(
text: $pageContent,
highlightRules: .markdown)
.onChange(of: pageContent) {
didChangeContent = true
}
}
.padding()
.onAppear(perform: loadContent)
@ -68,25 +70,33 @@ struct LocalizedPageContentView: View {
guard content != "" else {
pageContent = "New file"
loadedPageContentLanguage = nil
DispatchQueue.main.async {
didChangeContent = false
}
return
}
pageContent = content
loadedPageContentLanguage = language
checkContent()
} catch {
print("Failed to load page content: \(error)")
pageContent = "Failed to load"
loadedPageContentLanguage = nil
}
DispatchQueue.main.async {
didChangeContent = false
}
}
private func saveContent() {
guard let loadedPageContentLanguage else {
guard pageContent != "New file", pageContent != "" else {
// TODO: Delete file?
return
}
guard didChangeContent else {
return
}
do {
try page.content.storage.save(pageContent: pageContent, for: pageId, language: loadedPageContentLanguage)
try page.content.storage.save(pageContent: pageContent, for: pageId, language: language)
didChangeContent = false
} catch {
print("Failed to save content: \(error)")
}

View File

@ -34,10 +34,12 @@ struct LocalizedPageDetailView: View {
var body: some View {
VStack(alignment: .leading) {
HStack {
Text("Page URL String")
.font(.headline)
TextField("", text: $newUrlString)
.textFieldStyle(.roundedBorder)
Button("Update", action: setNewId)
.disabled(newUrlString.isEmpty || containsInvalidCharacters || idExists)
.disabled(newUrlString.isEmpty || containsInvalidCharacters || idExists)
}
.padding(.bottom)

View File

@ -74,11 +74,19 @@ struct PageContentResultsView: View {
text: "\(results.files.count + results.missingFiles.count) images and files",
items: results.files.sorted().map { $0.id })
.foregroundStyle(.secondary)
TextWithPopup(
symbol: .docBadgePlus,
text: "\(results.linkedPages.count + results.missingPages.count) page links",
items: results.linkedPages.sorted().map { $0.localized(in: language).title })
.foregroundStyle(.secondary)
TextWithPopup(
symbol: .globe,
text: "\(results.externalLinks.count) external links",
items: results.externalLinks.sorted())
.foregroundStyle(.secondary)
if !results.missingPages.isEmpty {
TextWithPopup(
symbol: .exclamationmarkTriangleFill,
@ -93,20 +101,11 @@ struct PageContentResultsView: View {
items: results.missingFiles.sorted())
.foregroundStyle(.red)
}
if !results.unknownCommands.isEmpty {
if !results.invalidCommands.isEmpty {
TextWithPopup(
symbol: .exclamationmarkTriangleFill,
text: "\(results.unknownCommands.count) unknown commands",
items: results.unknownCommands.sorted())
.foregroundStyle(.red)
}
if !results.invalidCommandArguments.isEmpty {
TextWithPopup(
symbol: .exclamationmarkTriangleFill,
text: "\(results.invalidCommandArguments.count) errors",
items: results.invalidCommandArguments.map {
"\($0.command.rawValue): \($0.arguments.joined(separator: ";"))"
})
text: "\(results.invalidCommands.count) invalid commands",
items: results.invalidCommands.map { $0.markdown }.sorted())
.foregroundStyle(.red)
}
}

View File

@ -24,16 +24,25 @@ struct PageContentView: View {
@EnvironmentObject
private var content: Content
@State
private var isGeneratingWebsite = false
init(page: Page) {
self.page = page
}
var body: some View {
LocalizedPageContentView(pageId: page.id, page: page.localized(in: language))
.id(page.id + language.rawValue)
if page.isExternalUrl {
VStack {
PageTitleView(page: page.localized(in: language))
.id(page.id + language.rawValue)
Spacer()
Text("No content available for external page")
.font(.title)
.foregroundStyle(.secondary)
Spacer()
}.padding()
} else {
LocalizedPageContentView(pageId: page.id, page: page.localized(in: language), language: language)
.id(page.id + language.rawValue)
}
}
}

View File

@ -62,6 +62,13 @@ struct PageDetailView: View {
}
.padding(.bottom)
Text("External url")
.font(.headline)
OptionalTextField("", text: $page.externalLink,
prompt: "External url")
.textFieldStyle(.roundedBorder)
.padding(.bottom)
HStack {
Text("Draft")
.font(.headline)
@ -120,19 +127,20 @@ struct PageDetailView: View {
return
}
isGeneratingWebsite = true
print("Generating page")
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
}
}
DispatchQueue.main.async {
isGeneratingWebsite = false
print("Done")
didGenerateWebsite = success
}
}
}