yattee/Model/Import Export Settings/ImportExportSettingsModel.swift

194 lines
6.8 KiB
Swift
Raw Normal View History

2024-02-01 22:54:16 +00:00
import Defaults
import Foundation
import SwiftUI
import SwiftyJSON
final class ImportExportSettingsModel: ObservableObject {
static let shared = ImportExportSettingsModel()
static var exportFile: URL {
YatteeApp.settingsExportDirectory
.appendingPathComponent("Yattee Settings from \(Constants.deviceName).\(settingsExtension)")
}
static var settingsExtension: String {
"yatteesettings"
}
enum ExportGroup: String, Identifiable, CaseIterable {
case browsingSettings
case playerSettings
case controlsSettings
case qualitySettings
case historySettings
case sponsorBlockSettings
case advancedSettings
case locationsSettings
case instances
case accounts
case accountsUnencryptedPasswords
case recentlyOpened
case otherData
static var settingsGroups: [Self] {
[.browsingSettings, .playerSettings, .controlsSettings, .qualitySettings, .historySettings, .sponsorBlockSettings, .advancedSettings]
}
static var locationsGroups: [Self] {
[.locationsSettings, .instances, .accounts, .accountsUnencryptedPasswords]
}
static var otherGroups: [Self] {
[.recentlyOpened, .otherData]
}
var id: RawValue {
rawValue
}
var label: String {
switch self {
case .browsingSettings:
2024-02-02 10:38:01 +00:00
return "Browsing"
2024-02-01 22:54:16 +00:00
case .playerSettings:
2024-02-02 10:38:01 +00:00
return "Player"
2024-02-01 22:54:16 +00:00
case .controlsSettings:
2024-02-02 10:38:01 +00:00
return "Controls"
2024-02-01 22:54:16 +00:00
case .qualitySettings:
2024-02-02 10:38:01 +00:00
return "Quality"
2024-02-01 22:54:16 +00:00
case .historySettings:
2024-02-02 10:38:01 +00:00
return "History"
2024-02-01 22:54:16 +00:00
case .sponsorBlockSettings:
2024-02-02 10:38:01 +00:00
return "SponsorBlock"
2024-02-01 22:54:16 +00:00
case .locationsSettings:
2024-02-02 10:38:01 +00:00
return "Public Locations"
2024-02-01 22:54:16 +00:00
case .instances:
2024-02-02 10:38:01 +00:00
return "Custom Locations"
2024-02-01 22:54:16 +00:00
case .accounts:
2024-02-02 10:38:01 +00:00
return "Accounts"
2024-02-01 22:54:16 +00:00
case .accountsUnencryptedPasswords:
2024-02-02 10:38:01 +00:00
return "Accounts passwords (unencrypted)"
2024-02-01 22:54:16 +00:00
case .advancedSettings:
2024-02-02 10:38:01 +00:00
return "Advanced"
2024-02-01 22:54:16 +00:00
case .recentlyOpened:
2024-02-02 10:38:01 +00:00
return "Recents"
2024-02-01 22:54:16 +00:00
case .otherData:
2024-02-02 10:38:01 +00:00
return "Other data"
2024-02-01 22:54:16 +00:00
}
}
}
@Published var selectedExportGroups = Set<ExportGroup>()
static var defaultExportGroups = Set<ExportGroup>([
.browsingSettings,
.playerSettings,
.controlsSettings,
.qualitySettings,
.historySettings,
.sponsorBlockSettings,
.locationsSettings,
.instances,
.accounts,
.advancedSettings
])
@Published var isExportInProgress = false
private var navigation = NavigationModel.shared
private var settings = SettingsModel.shared
func toggleExportGroupSelection(_ group: ExportGroup) {
if isGroupSelected(group) {
selectedExportGroups.remove(group)
} else {
selectedExportGroups.insert(group)
}
removeNotEnabledSelectedGroups()
}
func reset() {
isExportInProgress = false
selectedExportGroups = Self.defaultExportGroups
}
func reset(_ model: ImportSettingsFileModel? = nil) {
reset()
guard let model else { return }
selectedExportGroups = selectedExportGroups.filter { model.isGroupIncludedInFile($0) }
}
func exportAction() {
DispatchQueue.global(qos: .background).async { [weak self] in
var writingOptions: JSONSerialization.WritingOptions = []
#if DEBUG
writingOptions.insert(.prettyPrinted)
writingOptions.insert(.sortedKeys)
#endif
try? self?.jsonForExport?.rawString(options: writingOptions)?.write(to: Self.exportFile, atomically: true, encoding: String.Encoding.utf8)
#if os(macOS)
DispatchQueue.main.async { [weak self] in
self?.isExportInProgress = false
}
NSWorkspace.shared.selectFile(Self.exportFile.path, inFileViewerRootedAtPath: YatteeApp.settingsExportDirectory.path)
#endif
}
}
private var jsonForExport: JSON? {
[
"metadata": metadataJSON,
"browsingSettings": selectedExportGroups.contains(.browsingSettings) ? BrowsingSettingsGroupExporter().exportJSON : JSON(),
"playerSettings": selectedExportGroups.contains(.playerSettings) ? PlayerSettingsGroupExporter().exportJSON : JSON(),
"controlsSettings": selectedExportGroups.contains(.controlsSettings) ? ConstrolsSettingsGroupExporter().exportJSON : JSON(),
"qualitySettings": selectedExportGroups.contains(.qualitySettings) ? QualitySettingsGroupExporter().exportJSON : JSON(),
"historySettings": selectedExportGroups.contains(.historySettings) ? HistorySettingsGroupExporter().exportJSON : JSON(),
"sponsorBlockSettings": selectedExportGroups.contains(.sponsorBlockSettings) ? SponsorBlockSettingsGroupExporter().exportJSON : JSON(),
"locationsSettings": LocationsSettingsGroupExporter(
includePublicInstances: isGroupSelected(.locationsSettings),
includeInstances: isGroupSelected(.instances),
includeAccounts: isGroupSelected(.accounts),
includeAccountsUnencryptedPasswords: isGroupSelected(.accountsUnencryptedPasswords)
).exportJSON,
"advancedSettings": selectedExportGroups.contains(.advancedSettings) ? AdvancedSettingsGroupExporter().exportJSON : JSON(),
"recentlyOpened": selectedExportGroups.contains(.recentlyOpened) ? RecentlyOpenedExporter().exportJSON : JSON(),
"otherData": selectedExportGroups.contains(.otherData) ? OtherDataSettingsGroupExporter().exportJSON : JSON()
]
}
private var metadataJSON: JSON {
[
"build": YatteeApp.build,
"timestamp": "\(Date().timeIntervalSince1970)",
"platform": Constants.platform
]
}
func isGroupSelected(_ group: ExportGroup) -> Bool {
selectedExportGroups.contains(group)
}
func isGroupEnabled(_ group: ExportGroup) -> Bool {
switch group {
case .accounts:
return selectedExportGroups.contains(.instances)
case .accountsUnencryptedPasswords:
return selectedExportGroups.contains(.instances) && selectedExportGroups.contains(.accounts)
default:
return true
}
}
func removeNotEnabledSelectedGroups() {
selectedExportGroups = selectedExportGroups.filter { isGroupEnabled($0) }
}
var isExportAvailable: Bool {
!selectedExportGroups.isEmpty && !isExportInProgress
}
}