2025-02-18 22:05:19 +01:00

187 lines
5.0 KiB
Swift

import Foundation
import Combine
final class Settings: ChangeObservableItem {
@Published
var general: GeneralSettings
@Published
var paths: PathSettings
/// The items to show in the navigation bar
@Published
var navigation: NavigationSettings
@Published
var posts: PostSettings
@Published
var pages: PageSettings
@Published
var audioPlayer: AudioPlayerSettings
weak var content: Content?
var cancellables: Set<AnyCancellable> = []
init(general: GeneralSettings,
paths: PathSettings,
navigation: NavigationSettings,
posts: PostSettings,
pages: PageSettings,
audioPlayer: AudioPlayerSettings) {
self.general = general
self.paths = paths
self.navigation = navigation
self.posts = posts
self.pages = pages
self.audioPlayer = audioPlayer
}
func remove(_ file: FileResource) {
pages.remove(file)
posts.remove(file)
audioPlayer.remove(file)
}
func needsSaving() {
content?.needsSave()
}
}
// MARK: Storage
extension Settings {
convenience init(context: LoadingContext, data: Settings.Data) {
self.init(
general: .init(data: data.general),
paths: .init(data: data.paths),
navigation: .init(context: context, data: data.navigation),
posts: .init(context: context, data: data.posts),
pages: .init(context: context, data: data.pages),
audioPlayer: .init(context: context, data: data.audioPlayer))
content = context.content
}
func data(tagOverview: Tag?) -> Data {
.init(
general: general.data,
paths: paths.data,
navigation: navigation.data,
posts: posts.data,
pages: pages.data,
audioPlayer: audioPlayer.data,
tagOverview: tagOverview?.data)
}
struct Data: Codable, Equatable {
let general: GeneralSettings.Data
let paths: PathSettings.Data
let navigation: NavigationSettings.Data
let posts: PostSettings.Data
let pages: PageSettings.Data
let audioPlayer: AudioPlayerSettings.Data
let tagOverview: Tag.Data?
}
func saveToDisk(_ data: Data) -> Bool {
content?.storage.save(settings: data) ?? false
}
}
extension Settings {
static let `default`: Settings = .init(
general: .default,
paths: .default,
navigation: .default,
posts: .default,
pages: .default,
audioPlayer: .default)
}
extension GeneralSettings {
static let `default`: GeneralSettings = .init(
url: "https://example.com",
linkPreviewImageWidth: 1200,
linkPreviewImageHeight: 630,
remoteUserForUpload: "user",
remotePortForUpload: 22,
remotePathForUpload: "/home/user/web",
urlForPushNotification: nil)
}
extension AudioPlayerSettings {
static let `default`: AudioPlayerSettings = .init(
playlistCoverImageSize: 280,
smallCoverImageSize: 78,
audioPlayerJsFile: nil,
audioPlayerCssFile: nil,
german: .init(playlistText: "Wiedergabeliste"),
english: .init(playlistText: "Playlist"))
}
extension PostSettings {
static var `default`: PostSettings {
.init(postsPerPage: 25,
contentWidth: 600,
swiperCssFile: nil,
swiperJsFile: nil,
defaultCssFile: nil,
german: .init(
feedUrlPrefix: "blog",
defaultPageLinkText: "Anzeigen",
linkPreview: .init(
title: "Beiträge",
description: "Alle Beiträge")),
english: .init(
feedUrlPrefix: "blog",
defaultPageLinkText: "View",
linkPreview: .init(
title: "Blog posts",
description: "All blog posts"))
)
}
}
extension PathSettings {
static var `default`: PathSettings {
.init(
assetsOutputFolderPath: "asset",
pagesOutputFolderPath: "page",
imagesOutputFolderPath: "image",
filesOutputFolderPath: "file",
videosOutputFolderPath: "video",
audioOutputFolderPath: "audio",
tagsOutputFolderPath: "tag")
}
}
extension PageSettings {
static var `default`: PageSettings {
.init(contentWidth: 600,
largeImageWidth: 1200,
pageLinkImageSize: 180,
defaultCssFile: nil,
codeHighlightingJsFile: nil,
modelViewerJsFile: nil,
imageCompareJsFile: nil,
imageCompareCssFile: nil,
german: .init(
emptyPageTitle: "Leere Seite",
emptyPageText: "Diese Seite ist leer"),
english: .init(
emptyPageTitle: "Empty page",
emptyPageText: "This page is empty"))
}
}