yattee/Shared/Settings/AdvancedSettings.swift

239 lines
8.1 KiB
Swift
Raw Normal View History

import Defaults
import SwiftUI
struct AdvancedSettings: View {
@Default(.instancesManifest) private var instancesManifest
@Default(.showMPVPlaybackStats) private var showMPVPlaybackStats
2022-07-02 10:49:57 +00:00
@Default(.mpvCacheSecs) private var mpvCacheSecs
@Default(.mpvCachePauseWait) private var mpvCachePauseWait
2022-07-06 22:08:38 +00:00
@Default(.mpvEnableLogging) private var mpvEnableLogging
2022-11-11 18:55:18 +00:00
@Default(.countryOfPublicInstances) private var countryOfPublicInstances
@Default(.instances) private var instances
2022-07-06 22:08:38 +00:00
2022-11-11 18:55:18 +00:00
@EnvironmentObject<AccountsModel> private var accounts
@EnvironmentObject<NavigationModel> private var navigation
2022-07-06 22:08:38 +00:00
@EnvironmentObject<PlayerModel> private var player
2022-11-11 18:55:18 +00:00
@EnvironmentObject<SettingsModel> private var settings
2022-07-06 22:08:38 +00:00
2022-11-11 18:55:18 +00:00
@State private var countries = [String]()
2022-07-06 22:08:38 +00:00
@State private var filesToShare = [MPVClient.logFile]
2022-11-11 18:55:18 +00:00
@State private var presentingInstanceForm = false
@State private var presentingShareSheet = false
@State private var savedFormInstanceID: Instance.ID?
var body: some View {
VStack(alignment: .leading) {
#if os(macOS)
advancedSettings
2022-11-11 18:55:18 +00:00
locationsSettings
Spacer()
#else
List {
advancedSettings
2022-11-11 18:55:18 +00:00
locationsSettings
}
#if os(iOS)
2022-07-06 22:08:38 +00:00
.sheet(isPresented: $presentingShareSheet) {
ShareSheet(activityItems: filesToShare)
.id("logs-\(filesToShare.count)")
}
.listStyle(.insetGrouped)
#endif
#endif
}
2022-11-11 18:55:18 +00:00
.onAppear(perform: loadCountries)
.onChange(of: countryOfPublicInstances) { newCountry in
InstancesManifest.shared.setPublicAccount(newCountry, accounts: accounts, asCurrent: accounts.current?.isPublic ?? true)
}
.onChange(of: instancesManifest) { _ in
countries.removeAll()
}
.sheet(isPresented: $presentingInstanceForm) {
InstanceForm(savedInstanceID: $savedFormInstanceID)
}
#if os(tvOS)
.frame(maxWidth: 1000)
#endif
.navigationTitle("Advanced")
}
2022-07-06 22:08:38 +00:00
var logButton: some View {
Button {
#if os(macOS)
NSWorkspace.shared.selectFile(MPVClient.logFile.path, inFileViewerRootedAtPath: YatteeApp.logsDirectory.path)
#else
presentingShareSheet = true
#endif
} label: {
#if os(macOS)
2022-10-12 16:49:47 +00:00
let labelText = "Open logs in Finder".localized()
2022-07-06 22:08:38 +00:00
#else
2022-10-12 16:49:47 +00:00
let labelText = "Share Logs...".localized()
2022-07-06 22:08:38 +00:00
#endif
Text(labelText)
}
}
@ViewBuilder var advancedSettings: some View {
2022-07-02 10:49:57 +00:00
Section(header: SettingsHeader(text: "MPV"), footer: mpvFooter) {
showMPVPlaybackStatsToggle
2022-07-06 22:08:38 +00:00
#if !os(tvOS)
mpvEnableLoggingToggle
#endif
2022-07-02 10:49:57 +00:00
HStack {
Text("cache-secs")
2022-07-03 20:32:26 +00:00
.frame(minWidth: 140, alignment: .leading)
2022-07-02 10:49:57 +00:00
TextField("cache-secs", text: $mpvCacheSecs)
}
2022-07-03 20:32:26 +00:00
.multilineTextAlignment(.trailing)
2022-07-02 10:49:57 +00:00
HStack {
Text("cache-pause-wait")
2022-07-03 20:32:26 +00:00
.frame(minWidth: 140, alignment: .leading)
2022-07-02 10:49:57 +00:00
TextField("cache-pause-wait", text: $mpvCachePauseWait)
}
2022-07-03 20:32:26 +00:00
.multilineTextAlignment(.trailing)
2022-07-06 22:08:38 +00:00
if mpvEnableLogging {
logButton
}
2022-07-02 10:49:57 +00:00
}
Section(header: manifestHeader) {
TextField("URL", text: $instancesManifest)
2022-11-11 18:55:18 +00:00
Button("Reload manifest", action: loadCountries)
.disabled(instancesManifest.isEmpty)
2022-07-02 10:49:57 +00:00
#if !os(macOS)
.keyboardType(.webSearch)
#endif
.disableAutocorrection(true)
}
.padding(.bottom, 4)
2022-07-02 10:49:57 +00:00
}
2022-07-02 10:49:57 +00:00
@ViewBuilder var mpvFooter: some View {
2022-07-03 20:32:26 +00:00
let url = "https://mpv.io/manual/master"
2022-07-02 10:49:57 +00:00
VStack(alignment: .leading) {
Text("Restart the app to apply the settings above.")
2022-07-03 20:32:26 +00:00
VStack(alignment: .leading, spacing: 2) {
#if os(tvOS)
Text("More info can be found in MPV Documentation:")
Text(url)
#else
Text("More info can be found in:")
Link("MPV Documentation", destination: URL(string: url)!)
#if os(macOS)
.onHover(perform: onHover(_:))
#endif
#endif
2022-07-02 10:49:57 +00:00
}
}
2022-07-02 10:49:57 +00:00
.foregroundColor(.secondary)
}
var manifestHeader: some View {
2022-11-11 18:55:18 +00:00
SettingsHeader(text: "Locations Manifest".localized())
}
var showMPVPlaybackStatsToggle: some View {
2022-07-02 10:49:57 +00:00
Toggle("Show playback statistics", isOn: $showMPVPlaybackStats)
}
2022-07-03 20:32:26 +00:00
2022-07-06 22:08:38 +00:00
var mpvEnableLoggingToggle: some View {
Toggle("Enable logging", isOn: $mpvEnableLogging)
}
2022-07-03 20:32:26 +00:00
#if os(macOS)
private func onHover(_ inside: Bool) {
if inside {
NSCursor.pointingHand.push()
} else {
NSCursor.pop()
}
}
#endif
2022-11-11 18:55:18 +00:00
@ViewBuilder var locationsSettings: some View {
if !InstancesManifest.shared.manifestURL.isNil, !countries.isEmpty {
Section(header: SettingsHeader(text: "Public Locations".localized()), footer: countryFooter) {
Picker("Country", selection: $countryOfPublicInstances) {
Text("Don't use public locations").tag(String?.none)
ForEach(countries, id: \.self) { country in
Text(country).tag(Optional(country))
}
}
#if os(tvOS)
.pickerStyle(.inline)
#endif
.disabled(countries.isEmpty)
Button {
InstancesManifest.shared.changePublicAccount(accounts, settings: settings)
} label: {
if let account = accounts.current, account.isPublic {
Text("Switch to other public location")
} else {
Text("Switch to public locations")
}
}
.disabled(countryOfPublicInstances.isNil)
}
}
Section(header: SettingsHeader(text: "Custom Locations".localized())) {
#if os(macOS)
InstancesSettings()
.environmentObject(settings)
#else
ForEach(instances) { instance in
AccountsNavigationLink(instance: instance)
}
addInstanceButton
#endif
}
}
@ViewBuilder var countryFooter: some View {
if let account = accounts.current {
let locationType = account.isPublic ? (account.country ?? "Unknown") : "Custom".localized()
let description = account.isPublic ? account.url : account.instance?.description ?? "unknown".localized()
Text("Current: \(locationType)\n\(description)")
.foregroundColor(.secondary)
#if os(macOS)
.padding(.bottom, 10)
#endif
}
}
func loadCountries() {
InstancesManifest.shared.configure()
InstancesManifest.shared.instancesList?.load()
.onSuccess { response in
if let instances: [ManifestedInstance] = response.typedContent() {
self.countries = instances.map(\.country).unique().sorted()
}
}
.onFailure { _ in
settings.presentAlert(title: "Could not load locations manifest".localized())
}
}
private var addInstanceButton: some View {
Button {
presentingInstanceForm = true
} label: {
Label("Add Location...", systemImage: "plus")
}
}
}
struct AdvancedSettings_Previews: PreviewProvider {
static var previews: some View {
AdvancedSettings()
2022-11-11 18:55:18 +00:00
.injectFixtureEnvironmentObjects()
}
}