import Foundation extension Content { func saveToDisk() throws { guard storage.hasContentFolders else { print("Storage not initialized, not saving content") return } //print("Starting save") for page in pages { try storage.save(pageMetadata: page.pageFile, for: page.id) } for post in posts { try storage.save(post: post.postFile, for: post.id) } for tag in tags { try storage.save(tagMetadata: tag.tagFile, for: tag.id) } try storage.save(settings: settings.file) let fileDescriptions: [FileDescriptions] = files.sorted().compactMap { file in guard !file.english.isEmpty || !file.german.isEmpty else { return nil } return FileDescriptions( fileId: file.id, german: file.german.nonEmpty, english: file.english.nonEmpty) } try storage.save(fileDescriptions: fileDescriptions) try storage.save(tagOverview: tagOverview?.file) let externalFileList = files.filter { $0.isExternallyStored }.map { $0.id } try storage.save(externalFileList: externalFileList) do { try storage.deletePostFiles(notIn: posts.map { $0.id }) try storage.deletePageFiles(notIn: pages.map { $0.id }) try storage.deleteTagFiles(notIn: tags.map { $0.id }) try storage.deleteFileResources(notIn: files.map { $0.id }) } catch { print("Failed to remove unused files: \(error)") } } } private extension Page { var pageFile: PageFile { .init(isDraft: isDraft, externalLink: externalLink, tags: tags.map { $0.id }, createdDate: createdDate, startDate: startDate, endDate: hasEndDate ? endDate : nil, german: german.pageFile, english: english.pageFile) } } private extension LocalizedPage { var pageFile: LocalizedPageFile { .init(url: urlString, files: files.sorted(), externalFiles: externalFiles.sorted(), requiredFiles: requiredFiles.sorted(), title: title, linkPreviewImage: linkPreviewImage?.id, linkPreviewTitle: linkPreviewTitle, linkPreviewDescription: linkPreviewDescription, lastModifiedDate: lastModified, originalURL: originalUrl) } } private extension Post { var postFile: PostFile { .init( isDraft: isDraft, createdDate: createdDate, startDate: startDate, endDate: hasEndDate ? endDate : nil, tags: tags.map { $0.id }, german: german.postFile, english: english.postFile, linkedPageId: linkedPage?.id) } } private extension LocalizedPost { var postFile: LocalizedPostFile { .init(images: images.map { $0.id }, title: title.nonEmpty, content: text, lastModifiedDate: lastModified, linkPreviewImage: linkPreviewImage?.id, linkPreviewTitle: linkPreviewTitle, linkPreviewDescription: linkPreviewDescription) } } private extension Tag { var tagFile: TagFile { .init(id: id, isVisible: isVisible, german: german.tagFile, english: english.tagFile) } } private extension LocalizedTag { var tagFile: LocalizedTagFile { .init(urlComponent: urlComponent, name: name, subtitle: subtitle, description: description, thumbnail: linkPreviewImage?.id, originalURL: originalUrl) } } extension Settings { var file: SettingsFile { .init( paths: paths.file, navigationItems: navigationItems.map { .init(type: $0.itemType, id: $0.id) }, posts: posts.file, pages: pages.file, german: german.file, english: english.file) } } private extension PostSettings { var file: PostSettingsFile { .init(postsPerPage: postsPerPage, contentWidth: contentWidth, swiperCssFile: swiperCssFile?.id, swiperJsFile: swiperJsFile?.id, defaultCssFile: defaultCssFile?.id) } } private extension LocalizedPostSettings { var file: LocalizedPostSettingsFile { .init( feedTitle: title, feedDescription: description, feedUrlPrefix: feedUrlPrefix) } }