Rework content commands, add audio player
This commit is contained in:
@ -69,6 +69,7 @@ struct AddPageView: View {
|
||||
let page = Page(
|
||||
content: content,
|
||||
id: newPageId,
|
||||
externalLink: nil,
|
||||
isDraft: true,
|
||||
createdDate: .now,
|
||||
startDate: .now,
|
||||
|
@ -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)")
|
||||
}
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user