diff --git a/CHDataManagement.xcodeproj/project.pbxproj b/CHDataManagement.xcodeproj/project.pbxproj index 03fd03a..1f3dff4 100644 --- a/CHDataManagement.xcodeproj/project.pbxproj +++ b/CHDataManagement.xcodeproj/project.pbxproj @@ -193,6 +193,9 @@ E2FE0EE82D16D4A3002963B7 /* ConvertThrowing.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FE0EE72D16D4A3002963B7 /* ConvertThrowing.swift */; }; E2FE0EEC2D1C1253002963B7 /* MultiFileSelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FE0EEB2D1C124E002963B7 /* MultiFileSelectionView.swift */; }; E2FE0EEE2D1C22F3002963B7 /* InlineLinkProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FE0EED2D1C22EF002963B7 /* InlineLinkProcessor.swift */; }; + E2FE0EF42D1D6D2E002963B7 /* GeneralIcons.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FE0EF32D1D6D22002963B7 /* GeneralIcons.swift */; }; + E2FE0EF62D1D6DF1002963B7 /* Icon.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FE0EF52D1D6DEE002963B7 /* Icon.swift */; }; + E2FE0EF82D1D8110002963B7 /* IconCommandProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FE0EF72D1D810C002963B7 /* IconCommandProcessor.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -377,6 +380,9 @@ E2FE0EE72D16D4A3002963B7 /* ConvertThrowing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConvertThrowing.swift; sourceTree = ""; }; E2FE0EEB2D1C124E002963B7 /* MultiFileSelectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiFileSelectionView.swift; sourceTree = ""; }; E2FE0EED2D1C22EF002963B7 /* InlineLinkProcessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InlineLinkProcessor.swift; sourceTree = ""; }; + E2FE0EF32D1D6D22002963B7 /* GeneralIcons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralIcons.swift; sourceTree = ""; }; + E2FE0EF52D1D6DEE002963B7 /* Icon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Icon.swift; sourceTree = ""; }; + E2FE0EF72D1D810C002963B7 /* IconCommandProcessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconCommandProcessor.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -520,6 +526,8 @@ E29D31AB2D0DA52C0051B7F4 /* Icons */ = { isa = PBXGroup; children = ( + E2FE0EF52D1D6DEE002963B7 /* Icon.swift */, + E2FE0EF32D1D6D22002963B7 /* GeneralIcons.swift */, E29D31B42D0DA8490051B7F4 /* PageIcon.swift */, E29D31B22D0DA6E50051B7F4 /* ButtonIcons.swift */, E29D31B02D0DA5510051B7F4 /* ContentIcon.swift */, @@ -532,6 +540,7 @@ E29D31B62D0DAC030051B7F4 /* Page Content */ = { isa = PBXGroup; children = ( + E2FE0EF72D1D810C002963B7 /* IconCommandProcessor.swift */, E2FE0EED2D1C22EF002963B7 /* InlineLinkProcessor.swift */, E29D31BD2D0DB8560051B7F4 /* AudioPlayerCommand.swift */, E29D31BB2D0DB5110051B7F4 /* CommandProcessor.swift */, @@ -905,6 +914,7 @@ E2A37D192CEA36A90000979F /* LocalizedTag.swift in Sources */, E25DA59B2D024A2B00AEF16D /* DateItem.swift in Sources */, E29D31902D0B34870051B7F4 /* GenerationAnomaly.swift in Sources */, + E2FE0EF42D1D6D2E002963B7 /* GeneralIcons.swift in Sources */, E25DA5172CFF00F500AEF16D /* Content+Save.swift in Sources */, E229902E2D0F7280009F8D77 /* IdPropertyView.swift in Sources */, E29D31AD2D0DA5360051B7F4 /* AudioPlayerIcons.swift in Sources */, @@ -956,6 +966,7 @@ E21850392CFCA6C00090B18B /* WebsiteData+Mock.swift in Sources */, E229901E2D0E4364009F8D77 /* LocalizedItem.swift in Sources */, E29D31262D0370A80051B7F4 /* VideoOption.swift in Sources */, + E2FE0EF82D1D8110002963B7 /* IconCommandProcessor.swift in Sources */, E21850272CF3B42D0090B18B /* PostDetailView.swift in Sources */, E2A37D172CE73F1A0000979F /* TagFile.swift in Sources */, E29D318E2D0B2E680051B7F4 /* PageSettingsContentView.swift in Sources */, @@ -1009,6 +1020,7 @@ E218500B2CEE02FD0090B18B /* Content+Mock.swift in Sources */, E29D31472D04892E0051B7F4 /* FileListView.swift in Sources */, E218503D2CFCFD910090B18B /* LocalizedPostFeedSettingsView.swift in Sources */, + E2FE0EF62D1D6DF1002963B7 /* Icon.swift in Sources */, E29D31A52D0CD03F0051B7F4 /* FileSelectionView.swift in Sources */, E22990322D0F767B009F8D77 /* DatePropertyView.swift in Sources */, E2A21C302CB490F90060935B /* HorizontalCenter.swift in Sources */, diff --git a/CHDataManagement/Generator/Page Content/IconCommandProcessor.swift b/CHDataManagement/Generator/Page Content/IconCommandProcessor.swift new file mode 100644 index 0000000..b52a273 --- /dev/null +++ b/CHDataManagement/Generator/Page Content/IconCommandProcessor.swift @@ -0,0 +1,25 @@ + +struct IconCommandProcessor: CommandProcessor { + + let commandType: ShorthandMarkdownKey = .icons + + + let results: PageGenerationResults + + init(content: Content, results: PageGenerationResults) { + self.results = results + } + + func process(_ arguments: [String], markdown: Substring) -> String { + var icons = [PageIcon]() + for argument in arguments { + guard let icon = PageIcon(rawValue: argument) else { + results.invalid(command: .icons, markdown) + continue + } + icons.append(icon) + } + results.require(icons: icons) + return "" + } +} diff --git a/CHDataManagement/Generator/PageContentGenerator.swift b/CHDataManagement/Generator/PageContentGenerator.swift index 614e713..b69d9ce 100644 --- a/CHDataManagement/Generator/PageContentGenerator.swift +++ b/CHDataManagement/Generator/PageContentGenerator.swift @@ -23,6 +23,8 @@ final class PageContentParser { private let inlineLink: InlineLinkProcessor + private let icons: IconCommandProcessor + var largeImageWidth: Int { content.settings.pages.largeImageWidth } @@ -39,6 +41,7 @@ final class PageContentParser { self.labelHandler = .init(content: content, results: results) self.audioPlayer = .init(content: content, results: results) self.inlineLink = .init(content: content, results: results, language: language) + self.icons = .init(content: content, results: results) } func generatePage(from content: String) -> String { @@ -226,6 +229,8 @@ final class PageContentParser { return audioPlayer.process(arguments, markdown: markdown) case .tagLink: return handleTagLink(arguments, markdown: markdown) + case .icons: + return icons.process(arguments, markdown: markdown) } } diff --git a/CHDataManagement/Generator/PageGenerator.swift b/CHDataManagement/Generator/PageGenerator.swift index 71a4c91..073a14e 100644 --- a/CHDataManagement/Generator/PageGenerator.swift +++ b/CHDataManagement/Generator/PageGenerator.swift @@ -44,6 +44,7 @@ final class PageGenerator { language: language, dateString: page.dateText(in: language), title: localized.title, + showTitle: !localized.hideTitle, tags: tags, linkTitle: localized.linkPreviewTitle ?? localized.title, description: localized.linkPreviewDescription ?? "", diff --git a/CHDataManagement/Generator/ShorthandMarkdownKey.swift b/CHDataManagement/Generator/ShorthandMarkdownKey.swift index f3c7b7b..9816292 100644 --- a/CHDataManagement/Generator/ShorthandMarkdownKey.swift +++ b/CHDataManagement/Generator/ShorthandMarkdownKey.swift @@ -49,4 +49,8 @@ enum ShorthandMarkdownKey: String { /// Format: `![audio-player](;)` case audioPlayer = "audio-player" + /// Add svg icons to the page for use in html components + /// Format: `![icons](icon-id;...)` + case icons + } diff --git a/CHDataManagement/Model/Content+Generation.swift b/CHDataManagement/Model/Content+Generation.swift index 755ab78..370e782 100644 --- a/CHDataManagement/Model/Content+Generation.swift +++ b/CHDataManagement/Model/Content+Generation.swift @@ -15,6 +15,15 @@ extension Content { } } + func endCurrentGeneration() { + guard isGeneratingWebsite, shouldGenerateWebsite else { + return + } + DispatchQueue.main.async { + self.set(shouldGenerate: false) + } + } + func generatePostFeedPages() { performGenerationIfIdle { self.generatePostFeedPagesInternal() @@ -36,6 +45,7 @@ extension Content { let count = results.requiredFiles.count var completed = 0 for file in results.requiredFiles { + guard shouldGenerateWebsite else { return } defer { completed += 1 status("Copying required files: \(completed) / \(count)") @@ -59,6 +69,7 @@ extension Content { let count = images.count var completed = 0 for image in images { + guard shouldGenerateWebsite else { return } defer { completed += 1 status("Generating required images: \(completed) / \(count)") @@ -156,10 +167,12 @@ extension Content { return } self.set(isGenerating: true) + self.set(shouldGenerate: true) DispatchQueue.global(qos: .userInitiated).async { operation() DispatchQueue.main.async { self.set(isGenerating: false) + self.set(shouldGenerate: false) } } } @@ -177,6 +190,7 @@ extension Content { private func generatePagesInternal() { let count = pages.count for index in pages.indices { + guard shouldGenerateWebsite else { return } let page = pages[index] status("Generating pages: \(index) / \(count)") guard !page.isExternalUrl else { @@ -197,6 +211,7 @@ extension Content { private func generatePostFeedPagesInternal() { status("Generating post feed") for language in ContentLanguage.allCases { + guard shouldGenerateWebsite else { return } let results = results.makeResults(for: .feed, in: language) let generator = PostListPageGenerator( language: language, @@ -217,6 +232,7 @@ extension Content { private func generateTagPagesInternal() { let count = tags.count for index in tags.indices { + guard shouldGenerateWebsite else { return } let tag = tags[index] status("Generating tag pages: \(index) / \(count)") generatePagesInternal(for: tag) @@ -253,6 +269,7 @@ extension Content { private func generateTagOverviewPagesInternal() { status("Generating tag overview page") for language in ContentLanguage.allCases { + guard shouldGenerateWebsite else { return } let results = results.makeResults(for: .tagOverview, in: language) #warning("Create layout for tag overview page") } diff --git a/CHDataManagement/Model/Content+Load.swift b/CHDataManagement/Model/Content+Load.swift index 7574924..f7b9f62 100644 --- a/CHDataManagement/Model/Content+Load.swift +++ b/CHDataManagement/Model/Content+Load.swift @@ -34,7 +34,8 @@ extension Content { originalUrl: page.originalURL, linkPreviewImage: page.linkPreviewImage.map { images[$0] }, linkPreviewTitle: page.linkPreviewTitle, - linkPreviewDescription: page.linkPreviewDescription) + linkPreviewDescription: page.linkPreviewDescription, + hideTitle: page.hideTitle ?? false) } func loadFromDisk() throws { @@ -204,8 +205,8 @@ extension Content { endDate: page.endDate, german: convert(page.german, images: files), english: convert(page.english, images: files), - tags: page.tags.map { tags[$0]! }, - requiredFiles: page.requiredFiles?.map { files[$0]! } ?? []) + tags: page.tags.compactMap { tags[$0] }, + requiredFiles: page.requiredFiles?.compactMap { files[$0] } ?? []) } } diff --git a/CHDataManagement/Model/Content+Save.swift b/CHDataManagement/Model/Content+Save.swift index da28b87..19a6b58 100644 --- a/CHDataManagement/Model/Content+Save.swift +++ b/CHDataManagement/Model/Content+Save.swift @@ -77,7 +77,8 @@ private extension LocalizedPage { linkPreviewTitle: linkPreviewTitle, linkPreviewDescription: linkPreviewDescription, lastModifiedDate: lastModified, - originalURL: originalUrl) + originalURL: originalUrl, + hideTitle: hideTitle ? true : nil) } } diff --git a/CHDataManagement/Model/Content.swift b/CHDataManagement/Model/Content.swift index 8dcf224..66aa4fc 100644 --- a/CHDataManagement/Model/Content.swift +++ b/CHDataManagement/Model/Content.swift @@ -34,6 +34,8 @@ final class Content: ObservableObject { @Published private(set) var isGeneratingWebsite = false + private(set) var shouldGenerateWebsite = false + init(settings: Settings, posts: [Post], pages: [Page], @@ -84,6 +86,10 @@ final class Content: ObservableObject { self.isGeneratingWebsite = isGenerating } + func set(shouldGenerate: Bool) { + self.shouldGenerateWebsite = shouldGenerate + } + func add(_ file: FileResource) { // TODO: Insert at correct index? files.insert(file, at: 0) diff --git a/CHDataManagement/Model/FileResource.swift b/CHDataManagement/Model/FileResource.swift index 79da1ce..7a96512 100644 --- a/CHDataManagement/Model/FileResource.swift +++ b/CHDataManagement/Model/FileResource.swift @@ -95,7 +95,7 @@ final class FileResource: Item { return content.settings.paths.videosOutputFolderPath } if type.isAudio { - + return content.settings.paths.audioOutputFolderPath } if type.isAsset { return content.settings.paths.assetsOutputFolderPath diff --git a/CHDataManagement/Model/LocalizedPage.swift b/CHDataManagement/Model/LocalizedPage.swift index 4cac77a..3cb0d10 100644 --- a/CHDataManagement/Model/LocalizedPage.swift +++ b/CHDataManagement/Model/LocalizedPage.swift @@ -43,6 +43,9 @@ final class LocalizedPage: ObservableObject { @Published var linkPreviewDescription: String? + @Published + var hideTitle: Bool + init(content: Content, urlString: String, title: String, @@ -50,7 +53,8 @@ final class LocalizedPage: ObservableObject { originalUrl: String? = nil, linkPreviewImage: FileResource? = nil, linkPreviewTitle: String? = nil, - linkPreviewDescription: String? = nil) { + linkPreviewDescription: String? = nil, + hideTitle: Bool = false) { self.content = content self.urlString = urlString self.title = title @@ -59,6 +63,7 @@ final class LocalizedPage: ObservableObject { self.linkPreviewImage = linkPreviewImage self.linkPreviewTitle = linkPreviewTitle self.linkPreviewDescription = linkPreviewDescription + self.hideTitle = hideTitle } func isValid(urlComponent: String) -> Bool { diff --git a/CHDataManagement/Model/Settings/PathSettings.swift b/CHDataManagement/Model/Settings/PathSettings.swift index ea77f15..13067f1 100644 --- a/CHDataManagement/Model/Settings/PathSettings.swift +++ b/CHDataManagement/Model/Settings/PathSettings.swift @@ -17,6 +17,9 @@ final class PathSettings: ObservableObject { @Published var videosOutputFolderPath: String + @Published + var audioOutputFolderPath: String + @Published var tagsOutputFolderPath: String @@ -27,6 +30,7 @@ final class PathSettings: ObservableObject { self.filesOutputFolderPath = file.filesOutputFolderPath self.videosOutputFolderPath = file.videosOutputFolderPath self.tagsOutputFolderPath = file.tagsOutputFolderPath + self.audioOutputFolderPath = file.audioOutputFolderPath } var file: PathSettingsFile { @@ -35,6 +39,7 @@ final class PathSettings: ObservableObject { imagesOutputFolderPath: imagesOutputFolderPath, filesOutputFolderPath: filesOutputFolderPath, videosOutputFolderPath: videosOutputFolderPath, - tagsOutputFolderPath: tagsOutputFolderPath) + tagsOutputFolderPath: tagsOutputFolderPath, + audioOutputFolderPath: audioOutputFolderPath) } } diff --git a/CHDataManagement/Page Elements/ContentElements/Icons/ButtonIcons.swift b/CHDataManagement/Page Elements/ContentElements/Icons/ButtonIcons.swift index ef77f42..46bc1f5 100644 --- a/CHDataManagement/Page Elements/ContentElements/Icons/ButtonIcons.swift +++ b/CHDataManagement/Page Elements/ContentElements/Icons/ButtonIcons.swift @@ -1,36 +1,47 @@ -struct ButtonDownloadIcon: ContentIcon { +extension Icon { + struct ArrowDown: ContentIcon { - static let name = "icon-download" + static let name = "icon-download" - static let content = """ - - """ + static let content = """ + + """ + } } -struct ButtonExternalIcon: ContentIcon { +extension Icon { - static let name = "icon-external" + struct ArrowRight: ContentIcon { - static let content = """ - - """ + static let name = "icon-external" + + static let content = """ + + """ + } } -struct ButtonGitIcon: ContentIcon { +extension Icon { - static let name = "icon-git" + struct Git: ContentIcon { - static let content = """ - - """ + static let name = "icon-git" + + static let content = """ + + """ + } } -struct ButtonPlayIcon: ContentIcon { +extension Icon { - static let name = "icon-play-circle" + struct Play: ContentIcon { - static let content = """ - - """ + static let name = "icon-play-circle" + + static let content = """ + + """ + } } diff --git a/CHDataManagement/Page Elements/ContentElements/Icons/GeneralIcons.swift b/CHDataManagement/Page Elements/ContentElements/Icons/GeneralIcons.swift new file mode 100644 index 0000000..fa31a2c --- /dev/null +++ b/CHDataManagement/Page Elements/ContentElements/Icons/GeneralIcons.swift @@ -0,0 +1,84 @@ + +extension Icon { + + struct Calendar: ContentIcon { + + static let name = "icon-calendar" + + static let content = """ + + """ + } +} + +extension Icon { + + struct ClockFill: ContentIcon { + + static let name = "icon-clock-fill" + + static let content = """ + + """ + } +} + +extension Icon { + + struct File: ContentIcon { + + static let name = "icon-file" + + static let content = """ + + """ + } +} + +extension Icon { + + struct Globe: ContentIcon { + + static let name = "icon-globe" + + static let content = """ + + """ + } +} + +extension Icon { + + struct Location: ContentIcon { + + static let name = "icon-location" + + static let content = """ + + """ + } +} + +extension Icon { + + struct Poster: ContentIcon { + + static let name = "icon-poster" + + static let content = """ + + """ + } +} + +extension Icon { + + struct Video: ContentIcon { + + static let name = "icon-video" + + static let content = """ + + """ + } +} diff --git a/CHDataManagement/Page Elements/ContentElements/Icons/Icon.swift b/CHDataManagement/Page Elements/ContentElements/Icons/Icon.swift new file mode 100644 index 0000000..25dfbcf --- /dev/null +++ b/CHDataManagement/Page Elements/ContentElements/Icons/Icon.swift @@ -0,0 +1,4 @@ + +enum Icon { + +} diff --git a/CHDataManagement/Page Elements/ContentElements/Icons/PageIcon.swift b/CHDataManagement/Page Elements/ContentElements/Icons/PageIcon.swift index da459a6..e235534 100644 --- a/CHDataManagement/Page Elements/ContentElements/Icons/PageIcon.swift +++ b/CHDataManagement/Page Elements/ContentElements/Icons/PageIcon.swift @@ -1,6 +1,22 @@ enum PageIcon: String, CaseIterable { + // MARK: General + + case calendar + + case clockFill = "clock-fill" + + case file + + case globe + + case location + + case poster + + case video + // MARK: Statistics case statisticsTime = "time" @@ -44,16 +60,23 @@ enum PageIcon: String, CaseIterable { case .statisticsElevationDown: return StatisticsElevationDownIcon.self case .statisticsDistance: return StatisticsDistanceIcon.self case .statisticsEnergy: return StatisticsEnergyIcon.self - case .buttonDownload: return ButtonDownloadIcon.self - case .buttonExternalLink: return ButtonExternalIcon.self - case .buttonGitLink: return ButtonGitIcon.self - case .buttonPlay: return ButtonPlayIcon.self + case .buttonDownload: return Icon.ArrowDown.self + case .buttonExternalLink: return Icon.ArrowRight.self + case .buttonGitLink: return Icon.Git.self + case .buttonPlay: return Icon.Play.self case .audioPlayerPlaylist: return AudioPlayerPlaylistIcon.self case .audioPlayerClose: return AudioPlayerCloseIcon.self case .audioPlayerPlay: return AudioPlayerPlayIcon.self case .audioPlayerPause: return AudioPlayerPauseIcon.self case .audioPlayerPrevious: return AudioPlayerPreviousIcon.self case .audioPlayerNext: return AudioPlayerNextIcon.self + case .calendar: return Icon.Calendar.self + case .clockFill: return Icon.ClockFill.self + case .file: return Icon.File.self + case .globe: return Icon.Globe.self + case .location: return Icon.Location.self + case .poster: return Icon.Poster.self + case .video: return Icon.Video.self } } } diff --git a/CHDataManagement/Page Elements/ContentElements/Icons/StatisticsIcons.swift b/CHDataManagement/Page Elements/ContentElements/Icons/StatisticsIcons.swift index 64a1dc0..27c1278 100644 --- a/CHDataManagement/Page Elements/ContentElements/Icons/StatisticsIcons.swift +++ b/CHDataManagement/Page Elements/ContentElements/Icons/StatisticsIcons.swift @@ -1,10 +1,10 @@ struct StatisticsTimeIcon: ContentIcon { - static let name = "icon-time" + static let name = "icon-clock" static let content = """ - + """ } diff --git a/CHDataManagement/Pages/ContentPage.swift b/CHDataManagement/Pages/ContentPage.swift index 14f665d..221a7c7 100644 --- a/CHDataManagement/Pages/ContentPage.swift +++ b/CHDataManagement/Pages/ContentPage.swift @@ -12,6 +12,8 @@ struct ContentPage: HtmlProducer { private let title: String + private let showTitle: Bool + private let tags: [FeedEntryData.Tag] private let navigationBarLinks: [NavigationBar.Link] @@ -24,10 +26,21 @@ struct ContentPage: HtmlProducer { private let icons: Set - init(language: ContentLanguage, dateString: String, title: String, tags: [FeedEntryData.Tag], linkTitle: String, description: String, navigationBarLinks: [NavigationBar.Link], pageContent: String, headers: Set, footers: [String], icons: Set) { + init(language: ContentLanguage, + dateString: String, + title: String, + showTitle: Bool, + tags: [FeedEntryData.Tag], + linkTitle: String, + description: String, + navigationBarLinks: [NavigationBar.Link], + pageContent: String, + headers: Set, + footers: [String], icons: Set) { self.language = language self.dateString = dateString self.title = title + self.showTitle = showTitle self.tags = tags self.linkTitle = linkTitle self.description = description @@ -47,9 +60,11 @@ struct ContentPage: HtmlProducer { result += "
" result += "
" - result += "

\(dateString)

" - result += "

\(title)

" - result += TagList(tags: tags).content + if showTitle { + result += "

\(dateString)

" + result += "

\(title)

" + result += TagList(tags: tags).content + } result += symbols result += pageContent result += "
" @@ -59,6 +74,9 @@ struct ContentPage: HtmlProducer { } private var symbols: String { + guard !icons.isEmpty else { + return "" + } var result = "
" for icon in icons { result += icon.icon.content diff --git a/CHDataManagement/Storage/Model/PageFile.swift b/CHDataManagement/Storage/Model/PageFile.swift index 29bf113..376a506 100644 --- a/CHDataManagement/Storage/Model/PageFile.swift +++ b/CHDataManagement/Storage/Model/PageFile.swift @@ -47,6 +47,8 @@ struct LocalizedPageFile { let lastModifiedDate: Date? let originalURL: String? + + let hideTitle: Bool? } extension LocalizedPageFile: Codable { diff --git a/CHDataManagement/Storage/Model/Settings/PathSettingsFile.swift b/CHDataManagement/Storage/Model/Settings/PathSettingsFile.swift index df579d4..4b241bd 100644 --- a/CHDataManagement/Storage/Model/Settings/PathSettingsFile.swift +++ b/CHDataManagement/Storage/Model/Settings/PathSettingsFile.swift @@ -13,18 +13,22 @@ struct PathSettingsFile { let tagsOutputFolderPath: String + let audioOutputFolderPath: String + init(assetsOutputFolderPath: String, pagesOutputFolderPath: String, imagesOutputFolderPath: String, filesOutputFolderPath: String, videosOutputFolderPath: String, - tagsOutputFolderPath: String) { + tagsOutputFolderPath: String, + audioOutputFolderPath: String) { self.assetsOutputFolderPath = assetsOutputFolderPath self.pagesOutputFolderPath = pagesOutputFolderPath self.imagesOutputFolderPath = imagesOutputFolderPath self.filesOutputFolderPath = filesOutputFolderPath self.videosOutputFolderPath = videosOutputFolderPath self.tagsOutputFolderPath = tagsOutputFolderPath + self.audioOutputFolderPath = audioOutputFolderPath } } @@ -41,7 +45,8 @@ extension PathSettingsFile { imagesOutputFolderPath: "image", filesOutputFolderPath: "file", videosOutputFolderPath: "video", - tagsOutputFolderPath: "tag") + tagsOutputFolderPath: "tag", + audioOutputFolderPath: "audio") } } diff --git a/CHDataManagement/Views/Pages/LocalizedPageDetailView.swift b/CHDataManagement/Views/Pages/LocalizedPageDetailView.swift index b8e9655..13b65b2 100644 --- a/CHDataManagement/Views/Pages/LocalizedPageDetailView.swift +++ b/CHDataManagement/Views/Pages/LocalizedPageDetailView.swift @@ -18,6 +18,12 @@ struct LocalizedPageDetailView: View { update: { page.urlString = $0 }) .disabled(isExternalPage) + BoolPropertyView( + title: "Hide automatic title", + value: $page.hideTitle, + footer: "Prevent the date and title from being printed on the page") + .disabled(isExternalPage) + OptionalStringPropertyView( title: "Preview Title", text: $page.linkPreviewTitle, diff --git a/CHDataManagement/Views/Settings/Content/GenerationContentView.swift b/CHDataManagement/Views/Settings/Content/GenerationContentView.swift index efea01c..e6b0d99 100644 --- a/CHDataManagement/Views/Settings/Content/GenerationContentView.swift +++ b/CHDataManagement/Views/Settings/Content/GenerationContentView.swift @@ -15,12 +15,6 @@ struct GenerationContentView: View { self._selectedSection = selected } - @State - private var isGeneratingWebsite = false - - @State - private var generatorText: String = "" - var body: some View { switch selectedSection { case .folders, .navigationBar, .postFeed, .tagOverview: @@ -41,21 +35,24 @@ struct GenerationContentView: View { .padding(.bottom, 30) HStack { - Button(action: generateFullWebsite) { - Text("Generate") + Button { + if content.isGeneratingWebsite { + content.endCurrentGeneration() + } else { + generateFullWebsite() + } + } label: { + Text(content.isGeneratingWebsite ? "Cancel" : "Generate") } - Text(generatorText) - Spacer() - if isGeneratingWebsite { + if content.isGeneratingWebsite { ProgressView() .progressViewStyle(.circular) .frame(height: 25) } + Spacer() } - .disabled(isGeneratingWebsite) Text(content.generationStatus) - .font(.subheadline) - .padding() + .padding(.vertical, 5) HStack(spacing: 8) { Text("\(content.results.imagesToGenerate.count) images") Text("\(content.results.externalLinks.count) external links") diff --git a/CHDataManagement/Views/Settings/PathSettingsView.swift b/CHDataManagement/Views/Settings/PathSettingsView.swift index d1406e1..885f3b9 100644 --- a/CHDataManagement/Views/Settings/PathSettingsView.swift +++ b/CHDataManagement/Views/Settings/PathSettingsView.swift @@ -54,6 +54,11 @@ struct PathSettingsView: View { text: $content.settings.paths.videosOutputFolderPath, footer: "The path in the output folder where the generated videos are stored") + StringPropertyView( + title: "Audio output folder", + text: $content.settings.paths.audioOutputFolderPath, + footer: "The path in the output folder where the audio files are stored") + StringPropertyView( title: "Assets output folder", text: $content.settings.paths.assetsOutputFolderPath,