mirror of
https://github.com/yattee/yattee.git
synced 2024-11-09 15:58:20 +00:00
Redesigned settings (fixes #47)
This commit is contained in:
parent
520d69f37a
commit
3baa7a6893
@ -15,10 +15,10 @@ struct AccountsNavigationLink: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func removeInstanceButton(_ instance: Instance) -> some View {
|
private func removeInstanceButton(_ instance: Instance) -> some View {
|
||||||
if #available(iOS 15.0, *) {
|
Button {
|
||||||
return Button("Remove", role: .destructive) { removeAction(instance) }
|
removeAction(instance)
|
||||||
} else {
|
} label: {
|
||||||
return Button("Remove") { removeAction(instance) }
|
Label("Remove", systemImage: "trash")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
124
Shared/Settings/Help.swift
Normal file
124
Shared/Settings/Help.swift
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
import Foundation
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct Help: View {
|
||||||
|
static let wikiURL = URL(string: "https://github.com/yattee/yattee/wiki")!
|
||||||
|
static let matrixURL = URL(string: "https://tinyurl.com/yattee-matrix")!
|
||||||
|
static let issuesURL = URL(string: "https://github.com/yattee/yattee/issues")!
|
||||||
|
static let milestonesURL = URL(string: "https://github.com/yattee/yattee/milestones")!
|
||||||
|
static let donationsURL = URL(string: "https://github.com/yattee/yattee/wiki/Donations")!
|
||||||
|
static let contributingURL = URL(string: "https://github.com/yattee/yattee/wiki/Contributing")!
|
||||||
|
|
||||||
|
@Environment(\.openURL) private var openURL
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
Group {
|
||||||
|
ScrollView(.vertical, showsIndicators: false) {
|
||||||
|
VStack(alignment: .leading, spacing: 0) {
|
||||||
|
Section {
|
||||||
|
header("I am lost")
|
||||||
|
|
||||||
|
Text("You can find information about using Yattee in the Wiki pages.")
|
||||||
|
.padding(.bottom, 8)
|
||||||
|
|
||||||
|
helpItemLink("Wiki", url: Self.wikiURL, systemImage: "questionmark.circle")
|
||||||
|
.padding(.bottom, 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
Section {
|
||||||
|
header("I want to ask a question")
|
||||||
|
|
||||||
|
Text("Discussions take place in Matrix chat channel. It's a good spot for general questions.")
|
||||||
|
.padding(.bottom, 8)
|
||||||
|
|
||||||
|
helpItemLink("Matrix Channel", url: Self.matrixURL, systemImage: "message")
|
||||||
|
.padding(.bottom, 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
Section {
|
||||||
|
header("I found a bug /")
|
||||||
|
header("I have a feature request")
|
||||||
|
|
||||||
|
Text("Bugs and great feature ideas can be sent to the GitHub issues tracker. ")
|
||||||
|
Text("If you are reporting a bug, include all relevant details (especially: app\u{00a0}version, used device and system version, steps to reproduce).")
|
||||||
|
Text("If you are interested what's coming in future updates, you can track project Milestones.")
|
||||||
|
.padding(.bottom, 8)
|
||||||
|
|
||||||
|
VStack(alignment: .leading, spacing: 8) {
|
||||||
|
helpItemLink("Issues Tracker", url: Self.issuesURL, systemImage: "ladybug")
|
||||||
|
helpItemLink("Milestones", url: Self.milestonesURL, systemImage: "list.star")
|
||||||
|
}
|
||||||
|
.padding(.bottom, 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
Section {
|
||||||
|
header("I like this app!")
|
||||||
|
|
||||||
|
Text("That's nice to hear. It is fun to deliver apps other people want to use. " +
|
||||||
|
"You can consider donating to the project or help by contributing to new features development.")
|
||||||
|
.padding(.bottom, 8)
|
||||||
|
|
||||||
|
VStack(alignment: .leading, spacing: 8) {
|
||||||
|
helpItemLink("Donations", url: Self.donationsURL, systemImage: "dollarsign.circle")
|
||||||
|
helpItemLink("Contributing", url: Self.contributingURL, systemImage: "hammer")
|
||||||
|
}
|
||||||
|
.padding(.bottom, 8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if os(iOS)
|
||||||
|
.padding(.horizontal)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if os(tvOS)
|
||||||
|
.frame(maxWidth: 1000)
|
||||||
|
#else
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
#endif
|
||||||
|
.navigationTitle("Help")
|
||||||
|
}
|
||||||
|
|
||||||
|
func header(_ text: String) -> some View {
|
||||||
|
Text(text)
|
||||||
|
.fontWeight(.bold)
|
||||||
|
.font(.title3)
|
||||||
|
.padding(.bottom, 6)
|
||||||
|
}
|
||||||
|
|
||||||
|
func helpItemLink(_ label: String, url: URL, systemImage: String) -> some View {
|
||||||
|
Group {
|
||||||
|
#if os(tvOS)
|
||||||
|
VStack {
|
||||||
|
Button {} label: {
|
||||||
|
HStack(spacing: 8) {
|
||||||
|
Image(systemName: systemImage)
|
||||||
|
Text(label)
|
||||||
|
}
|
||||||
|
.font(.system(size: 25).bold())
|
||||||
|
}
|
||||||
|
|
||||||
|
Text(url.absoluteString)
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
#else
|
||||||
|
Button {
|
||||||
|
openURL(url)
|
||||||
|
} label: {
|
||||||
|
Label(label, systemImage: systemImage)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Help_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
Help()
|
||||||
|
}
|
||||||
|
}
|
@ -19,31 +19,66 @@ struct HistorySettings: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Group {
|
Group {
|
||||||
Section(header: SettingsHeader(text: "History")) {
|
#if os(macOS)
|
||||||
Toggle("Save recent queries and channels", isOn: $saveRecents)
|
sections
|
||||||
Toggle("Save history of played videos", isOn: $saveHistory)
|
#else
|
||||||
Toggle("Show progress of watching on thumbnails", isOn: $showWatchingProgress)
|
List {
|
||||||
.disabled(!saveHistory)
|
sections
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#if os(tvOS)
|
||||||
|
.frame(maxWidth: 1000)
|
||||||
|
#elseif os(iOS)
|
||||||
|
.listStyle(.insetGrouped)
|
||||||
|
#endif
|
||||||
|
.navigationTitle("History")
|
||||||
|
}
|
||||||
|
|
||||||
|
private var sections: some View {
|
||||||
|
Group {
|
||||||
|
#if os(tvOS)
|
||||||
|
Section(header: SettingsHeader(text: "History")) {
|
||||||
|
Toggle("Save history of searches, channels and playlists", isOn: $saveRecents)
|
||||||
|
Toggle("Save history of played videos", isOn: $saveHistory)
|
||||||
|
Toggle("Show progress of watching on thumbnails", isOn: $showWatchingProgress)
|
||||||
|
.disabled(!saveHistory)
|
||||||
|
|
||||||
|
watchedVideoPlayNowBehaviorPicker
|
||||||
|
|
||||||
#if !os(tvOS)
|
|
||||||
watchedThresholdPicker
|
watchedThresholdPicker
|
||||||
|
resetWatchedStatusOnPlayingToggle
|
||||||
watchedVideoStylePicker
|
watchedVideoStylePicker
|
||||||
watchedVideoBadgeColorPicker
|
watchedVideoBadgeColorPicker
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
Section(header: SettingsHeader(text: "History")) {
|
||||||
|
Toggle("Save history of searches, channels and playlists", isOn: $saveRecents)
|
||||||
|
Toggle("Save history of played videos", isOn: $saveHistory)
|
||||||
|
Toggle("Show progress of watching on thumbnails", isOn: $showWatchingProgress)
|
||||||
|
.disabled(!saveHistory)
|
||||||
|
}
|
||||||
|
|
||||||
|
Section(header: SettingsHeader(text: "Watched")) {
|
||||||
watchedVideoPlayNowBehaviorPicker
|
watchedVideoPlayNowBehaviorPicker
|
||||||
|
#if os(macOS)
|
||||||
|
.padding(.top, 1)
|
||||||
|
#endif
|
||||||
|
watchedThresholdPicker
|
||||||
resetWatchedStatusOnPlayingToggle
|
resetWatchedStatusOnPlayingToggle
|
||||||
|
}
|
||||||
|
|
||||||
|
Section(header: SettingsHeader(text: "Interface")) {
|
||||||
|
watchedVideoStylePicker
|
||||||
|
#if os(macOS)
|
||||||
|
.padding(.top, 1)
|
||||||
|
#endif
|
||||||
|
watchedVideoBadgeColorPicker
|
||||||
|
}
|
||||||
|
|
||||||
|
#if os(macOS)
|
||||||
|
Spacer()
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
#if os(tvOS)
|
|
||||||
watchedThresholdPicker
|
|
||||||
watchedVideoStylePicker
|
|
||||||
watchedVideoBadgeColorPicker
|
|
||||||
watchedVideoPlayNowBehaviorPicker
|
|
||||||
resetWatchedStatusOnPlayingToggle
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if os(macOS)
|
|
||||||
Spacer()
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
clearHistoryButton
|
clearHistoryButton
|
||||||
@ -51,7 +86,7 @@ struct HistorySettings: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var watchedThresholdPicker: some View {
|
private var watchedThresholdPicker: some View {
|
||||||
Section(header: header("Mark video as watched after playing")) {
|
Section(header: SettingsHeader(text: "Mark video as watched after playing", secondary: true)) {
|
||||||
Picker("Mark video as watched after playing", selection: $watchedThreshold) {
|
Picker("Mark video as watched after playing", selection: $watchedThreshold) {
|
||||||
ForEach(Self.watchedThresholds, id: \.self) { threshold in
|
ForEach(Self.watchedThresholds, id: \.self) { threshold in
|
||||||
Text("\(threshold)%").tag(threshold)
|
Text("\(threshold)%").tag(threshold)
|
||||||
@ -69,7 +104,7 @@ struct HistorySettings: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var watchedVideoStylePicker: some View {
|
private var watchedVideoStylePicker: some View {
|
||||||
Section(header: header("Mark watched videos with")) {
|
Section(header: SettingsHeader(text: "Mark watched videos with", secondary: true)) {
|
||||||
Picker("Mark watched videos with", selection: $watchedVideoStyle) {
|
Picker("Mark watched videos with", selection: $watchedVideoStyle) {
|
||||||
Text("Nothing").tag(WatchedVideoStyle.nothing)
|
Text("Nothing").tag(WatchedVideoStyle.nothing)
|
||||||
Text("Badge").tag(WatchedVideoStyle.badge)
|
Text("Badge").tag(WatchedVideoStyle.badge)
|
||||||
@ -88,7 +123,7 @@ struct HistorySettings: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var watchedVideoBadgeColorPicker: some View {
|
private var watchedVideoBadgeColorPicker: some View {
|
||||||
Section(header: header("Badge color")) {
|
Section(header: SettingsHeader(text: "Badge color", secondary: true)) {
|
||||||
Picker("Badge color", selection: $watchedVideoBadgeColor) {
|
Picker("Badge color", selection: $watchedVideoBadgeColor) {
|
||||||
Text("Based on system color scheme").tag(WatchedVideoBadgeColor.colorSchemeBased)
|
Text("Based on system color scheme").tag(WatchedVideoBadgeColor.colorSchemeBased)
|
||||||
Text("Blue").tag(WatchedVideoBadgeColor.blue)
|
Text("Blue").tag(WatchedVideoBadgeColor.blue)
|
||||||
@ -96,6 +131,7 @@ struct HistorySettings: View {
|
|||||||
}
|
}
|
||||||
.disabled(!saveHistory)
|
.disabled(!saveHistory)
|
||||||
.disabled(watchedVideoStyle == .decreasedOpacity)
|
.disabled(watchedVideoStyle == .decreasedOpacity)
|
||||||
|
.disabled(watchedVideoStyle == .nothing)
|
||||||
.labelsHidden()
|
.labelsHidden()
|
||||||
|
|
||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
@ -107,7 +143,7 @@ struct HistorySettings: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var watchedVideoPlayNowBehaviorPicker: some View {
|
private var watchedVideoPlayNowBehaviorPicker: some View {
|
||||||
Section(header: header("When partially watched video is played")) {
|
Section(header: SettingsHeader(text: "When partially watched video is played", secondary: true)) {
|
||||||
Picker("When partially watched video is played", selection: $watchedVideoPlayNowBehavior) {
|
Picker("When partially watched video is played", selection: $watchedVideoPlayNowBehavior) {
|
||||||
Text("Continue").tag(WatchedVideoPlayNowBehavior.continue)
|
Text("Continue").tag(WatchedVideoPlayNowBehavior.continue)
|
||||||
Text("Restart").tag(WatchedVideoPlayNowBehavior.restart)
|
Text("Restart").tag(WatchedVideoPlayNowBehavior.restart)
|
||||||
@ -125,6 +161,7 @@ struct HistorySettings: View {
|
|||||||
|
|
||||||
private var resetWatchedStatusOnPlayingToggle: some View {
|
private var resetWatchedStatusOnPlayingToggle: some View {
|
||||||
Toggle("Reset watched status when playing again", isOn: $resetWatchedStatusOnPlaying)
|
Toggle("Reset watched status when playing again", isOn: $resetWatchedStatusOnPlaying)
|
||||||
|
.disabled(!saveHistory)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var clearHistoryButton: some View {
|
private var clearHistoryButton: some View {
|
||||||
@ -149,19 +186,6 @@ struct HistorySettings: View {
|
|||||||
.foregroundColor(.red)
|
.foregroundColor(.red)
|
||||||
.disabled(!saveHistory)
|
.disabled(!saveHistory)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func header(_ text: String) -> some View {
|
|
||||||
#if os(iOS)
|
|
||||||
return EmptyView()
|
|
||||||
#elseif os(macOS)
|
|
||||||
return Text(text)
|
|
||||||
.opacity(saveHistory ? 1 : 0.3)
|
|
||||||
#else
|
|
||||||
return Text(text)
|
|
||||||
.foregroundColor(.secondary)
|
|
||||||
.opacity(saveHistory ? 1 : 0.2)
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct HistorySettings_Previews: PreviewProvider {
|
struct HistorySettings_Previews: PreviewProvider {
|
||||||
|
@ -14,25 +14,7 @@ struct InstanceSettings: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
List {
|
List {
|
||||||
if instance.app.hasFrontendURL {
|
Section(header: Text("Accounts")) {
|
||||||
Section(header: Text("Frontend URL")) {
|
|
||||||
TextField(
|
|
||||||
"Frontend URL",
|
|
||||||
text: $frontendURL
|
|
||||||
)
|
|
||||||
.onAppear {
|
|
||||||
frontendURL = instance.frontendURL ?? ""
|
|
||||||
}
|
|
||||||
.onChange(of: frontendURL) { newValue in
|
|
||||||
InstancesModel.setFrontendURL(instance, newValue)
|
|
||||||
}
|
|
||||||
.labelsHidden()
|
|
||||||
.autocapitalization(.none)
|
|
||||||
.keyboardType(.URL)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Section(header: Text("Accounts"), footer: sectionFooter) {
|
|
||||||
if instance.app.supportsAccounts {
|
if instance.app.supportsAccounts {
|
||||||
ForEach(InstancesModel.accounts(instanceID), id: \.self) { account in
|
ForEach(InstancesModel.accounts(instanceID), id: \.self) { account in
|
||||||
#if os(tvOS)
|
#if os(tvOS)
|
||||||
@ -54,15 +36,21 @@ struct InstanceSettings: View {
|
|||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
.contextMenu {
|
.contextMenu {
|
||||||
Button("Remove") { removeAccount(account) }
|
Button {
|
||||||
|
removeAccount(account)
|
||||||
|
} label: {
|
||||||
|
Label("Remove", systemImage: "trash")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
.redrawOn(change: accountsChanged)
|
.redrawOn(change: accountsChanged)
|
||||||
|
|
||||||
Button("Add account...") {
|
Button {
|
||||||
presentingAccountForm = true
|
presentingAccountForm = true
|
||||||
|
} label: {
|
||||||
|
Label("Add Account...", systemImage: "plus")
|
||||||
}
|
}
|
||||||
.sheet(isPresented: $presentingAccountForm, onDismiss: { accountsChanged.toggle() }) {
|
.sheet(isPresented: $presentingAccountForm, onDismiss: { accountsChanged.toggle() }) {
|
||||||
AccountForm(instance: instance)
|
AccountForm(instance: instance)
|
||||||
@ -75,6 +63,23 @@ struct InstanceSettings: View {
|
|||||||
.foregroundColor(.secondary)
|
.foregroundColor(.secondary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if instance.app.hasFrontendURL {
|
||||||
|
Section(header: Text("Frontend URL")) {
|
||||||
|
TextField(
|
||||||
|
"Frontend URL",
|
||||||
|
text: $frontendURL
|
||||||
|
)
|
||||||
|
.onAppear {
|
||||||
|
frontendURL = instance.frontendURL ?? ""
|
||||||
|
}
|
||||||
|
.onChange(of: frontendURL) { newValue in
|
||||||
|
InstancesModel.setFrontendURL(instance, newValue)
|
||||||
|
}
|
||||||
|
.labelsHidden()
|
||||||
|
.autocapitalization(.none)
|
||||||
|
.keyboardType(.URL)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#if os(tvOS)
|
#if os(tvOS)
|
||||||
.frame(maxWidth: 1000)
|
.frame(maxWidth: 1000)
|
||||||
@ -85,15 +90,6 @@ struct InstanceSettings: View {
|
|||||||
.navigationTitle(instance.description)
|
.navigationTitle(instance.description)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var sectionFooter: some View {
|
|
||||||
if !instance.app.supportsAccounts {
|
|
||||||
return Text("")
|
|
||||||
}
|
|
||||||
|
|
||||||
return Text("Tap and hold to remove account")
|
|
||||||
.foregroundColor(.secondary)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func removeAccount(_ account: Account) {
|
private func removeAccount(_ account: Account) {
|
||||||
AccountsModel.remove(account)
|
AccountsModel.remove(account)
|
||||||
accountsChanged.toggle()
|
accountsChanged.toggle()
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
import Defaults
|
import Defaults
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct PlaybackSettings: View {
|
struct PlayerSettings: View {
|
||||||
@Default(.instances) private var instances
|
@Default(.instances) private var instances
|
||||||
@Default(.playerInstanceID) private var playerInstanceID
|
@Default(.playerInstanceID) private var playerInstanceID
|
||||||
@Default(.quality) private var quality
|
@Default(.quality) private var quality
|
||||||
|
@Default(.commentsInstanceID) private var commentsInstanceID
|
||||||
|
|
||||||
|
#if !os(tvOS)
|
||||||
|
@Default(.commentsPlacement) private var commentsPlacement
|
||||||
|
#endif
|
||||||
|
|
||||||
@Default(.playerSidebar) private var playerSidebar
|
@Default(.playerSidebar) private var playerSidebar
|
||||||
@Default(.showHistoryInPlayer) private var showHistory
|
@Default(.showHistoryInPlayer) private var showHistory
|
||||||
@Default(.showKeywords) private var showKeywords
|
@Default(.showKeywords) private var showKeywords
|
||||||
@ -29,66 +35,74 @@ struct PlaybackSettings: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Group {
|
Group {
|
||||||
#if os(iOS)
|
#if os(macOS)
|
||||||
Section(header: SettingsHeader(text: "Player")) {
|
sections
|
||||||
sourcePicker
|
|
||||||
qualityPicker
|
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
#else
|
||||||
|
List {
|
||||||
|
sections
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#if os(tvOS)
|
||||||
|
.frame(maxWidth: 1000)
|
||||||
|
#elseif os(iOS)
|
||||||
|
.listStyle(.insetGrouped)
|
||||||
|
#endif
|
||||||
|
.navigationTitle("Player")
|
||||||
|
}
|
||||||
|
|
||||||
|
private var sections: some View {
|
||||||
|
Group {
|
||||||
|
Section(header: SettingsHeader(text: "Playback")) {
|
||||||
|
sourcePicker
|
||||||
|
qualityPicker
|
||||||
|
pauseOnHidingPlayerToggle
|
||||||
|
}
|
||||||
|
|
||||||
|
Section(header: SettingsHeader(text: "Comments")) {
|
||||||
|
commentsInstancePicker
|
||||||
|
#if !os(tvOS)
|
||||||
|
commentsPlacementPicker
|
||||||
|
.disabled(!CommentsModel.enabled)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Section(header: SettingsHeader(text: "Interface")) {
|
||||||
|
#if os(iOS)
|
||||||
if idiom == .pad {
|
if idiom == .pad {
|
||||||
sidebarPicker
|
sidebarPicker
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
keywordsToggle
|
|
||||||
showHistoryToggle
|
|
||||||
channelSubscribersToggle
|
|
||||||
pauseOnHidingPlayerToggle
|
|
||||||
|
|
||||||
if idiom == .pad {
|
|
||||||
enterFullscreenInLandscapeToggle
|
|
||||||
}
|
|
||||||
|
|
||||||
honorSystemOrientationLockToggle
|
|
||||||
lockLandscapeWhenEnteringFullscreenToggle
|
|
||||||
}
|
|
||||||
|
|
||||||
Section(header: SettingsHeader(text: "Picture in Picture")) {
|
|
||||||
closePiPOnNavigationToggle
|
|
||||||
closePiPOnOpeningPlayerToggle
|
|
||||||
closePiPAndOpenPlayerOnEnteringForegroundToggle
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
Section(header: SettingsHeader(text: "Source")) {
|
|
||||||
sourcePicker
|
|
||||||
}
|
|
||||||
|
|
||||||
Section(header: SettingsHeader(text: "Quality")) {
|
|
||||||
qualityPicker
|
|
||||||
}
|
|
||||||
|
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
Section(header: SettingsHeader(text: "Sidebar")) {
|
sidebarPicker
|
||||||
sidebarPicker
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
keywordsToggle
|
keywordsToggle
|
||||||
showHistoryToggle
|
showHistoryToggle
|
||||||
channelSubscribersToggle
|
channelSubscribersToggle
|
||||||
pauseOnHidingPlayerToggle
|
}
|
||||||
|
|
||||||
Section(header: SettingsHeader(text: "Picture in Picture")) {
|
#if os(iOS)
|
||||||
closePiPOnNavigationToggle
|
Section(header: SettingsHeader(text: "Orientation")) {
|
||||||
closePiPOnOpeningPlayerToggle
|
if idiom == .pad {
|
||||||
#if !os(macOS)
|
enterFullscreenInLandscapeToggle
|
||||||
closePiPAndOpenPlayerOnEnteringForegroundToggle
|
}
|
||||||
#endif
|
honorSystemOrientationLockToggle
|
||||||
|
lockLandscapeWhenEnteringFullscreenToggle
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
#if os(macOS)
|
Section(header: SettingsHeader(text: "Picture in Picture")) {
|
||||||
Spacer()
|
closePiPOnNavigationToggle
|
||||||
#endif
|
closePiPOnOpeningPlayerToggle
|
||||||
|
#if !os(macOS)
|
||||||
|
closePiPAndOpenPlayerOnEnteringForegroundToggle
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var sourcePicker: some View {
|
private var sourcePicker: some View {
|
||||||
@ -122,17 +136,46 @@ struct PlaybackSettings: View {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var commentsInstancePicker: some View {
|
||||||
|
Picker("Source", selection: $commentsInstanceID) {
|
||||||
|
Text("Disabled").tag(Optional(""))
|
||||||
|
|
||||||
|
ForEach(InstancesModel.all.filter { $0.app.supportsComments }) { instance in
|
||||||
|
Text(instance.description).tag(Optional(instance.id))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.labelsHidden()
|
||||||
|
#if os(iOS)
|
||||||
|
.pickerStyle(.automatic)
|
||||||
|
#elseif os(tvOS)
|
||||||
|
.pickerStyle(.inline)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !os(tvOS)
|
||||||
|
private var commentsPlacementPicker: some View {
|
||||||
|
Picker("Placement", selection: $commentsPlacement) {
|
||||||
|
Text("Below video description").tag(CommentsPlacement.info)
|
||||||
|
Text("Separate tab").tag(CommentsPlacement.separate)
|
||||||
|
}
|
||||||
|
.labelsHidden()
|
||||||
|
#if os(iOS)
|
||||||
|
.pickerStyle(.automatic)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
private var sidebarPicker: some View {
|
private var sidebarPicker: some View {
|
||||||
Picker("Sidebar", selection: $playerSidebar) {
|
Picker("Sidebar", selection: $playerSidebar) {
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
Text("Show").tag(PlayerSidebarSetting.always)
|
Text("Show sidebar").tag(PlayerSidebarSetting.always)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
Text("Show sidebar when space permits").tag(PlayerSidebarSetting.whenFits)
|
Text("Show sidebar when space permits").tag(PlayerSidebarSetting.whenFits)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Text("Hide").tag(PlayerSidebarSetting.never)
|
Text("Hide sidebar").tag(PlayerSidebarSetting.never)
|
||||||
}
|
}
|
||||||
.labelsHidden()
|
.labelsHidden()
|
||||||
|
|
||||||
@ -144,15 +187,15 @@ struct PlaybackSettings: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var keywordsToggle: some View {
|
private var keywordsToggle: some View {
|
||||||
Toggle("Show video keywords", isOn: $showKeywords)
|
Toggle("Show keywords", isOn: $showKeywords)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var showHistoryToggle: some View {
|
private var showHistoryToggle: some View {
|
||||||
Toggle("Show history of videos", isOn: $showHistory)
|
Toggle("Show history", isOn: $showHistory)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var channelSubscribersToggle: some View {
|
private var channelSubscribersToggle: some View {
|
||||||
Toggle("Show channel subscribers count", isOn: $channelSubscribers)
|
Toggle("Show subscribers count", isOn: $channelSubscribers)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var pauseOnHidingPlayerToggle: some View {
|
private var pauseOnHidingPlayerToggle: some View {
|
||||||
@ -161,7 +204,7 @@ struct PlaybackSettings: View {
|
|||||||
|
|
||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
private var honorSystemOrientationLockToggle: some View {
|
private var honorSystemOrientationLockToggle: some View {
|
||||||
Toggle("Honor system orientation lock", isOn: $honorSystemOrientationLock)
|
Toggle("Honor orientation lock", isOn: $honorSystemOrientationLock)
|
||||||
.disabled(!enterFullscreenInLandscape)
|
.disabled(!enterFullscreenInLandscape)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +213,7 @@ struct PlaybackSettings: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var lockLandscapeWhenEnteringFullscreenToggle: some View {
|
private var lockLandscapeWhenEnteringFullscreenToggle: some View {
|
||||||
Toggle("Lock landscape orientation when entering fullscreen", isOn: $lockLandscapeWhenEnteringFullscreen)
|
Toggle("Lock landscape on rotation", isOn: $lockLandscapeWhenEnteringFullscreen)
|
||||||
.disabled(!enterFullscreenInLandscape)
|
.disabled(!enterFullscreenInLandscape)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -192,7 +235,7 @@ struct PlaybackSettings: View {
|
|||||||
|
|
||||||
struct PlaybackSettings_Previews: PreviewProvider {
|
struct PlaybackSettings_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
PlaybackSettings()
|
PlayerSettings()
|
||||||
.injectFixtureEnvironmentObjects()
|
.injectFixtureEnvironmentObjects()
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,152 +0,0 @@
|
|||||||
import Defaults
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct ServicesSettings: View {
|
|
||||||
@Default(.sponsorBlockInstance) private var sponsorBlockInstance
|
|
||||||
@Default(.sponsorBlockCategories) private var sponsorBlockCategories
|
|
||||||
@Default(.commentsInstanceID) private var commentsInstanceID
|
|
||||||
|
|
||||||
#if !os(tvOS)
|
|
||||||
@Default(.commentsPlacement) private var commentsPlacement
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
Section(header: SettingsHeader(text: "Comments")) {
|
|
||||||
commentsInstancePicker
|
|
||||||
#if !os(tvOS)
|
|
||||||
commentsPlacementPicker
|
|
||||||
.disabled(!CommentsModel.enabled)
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
Section(header: SettingsHeader(text: "SponsorBlock API")) {
|
|
||||||
TextField(
|
|
||||||
"SponsorBlock API Instance",
|
|
||||||
text: $sponsorBlockInstance
|
|
||||||
)
|
|
||||||
.labelsHidden()
|
|
||||||
#if !os(macOS)
|
|
||||||
.autocapitalization(.none)
|
|
||||||
.keyboardType(.URL)
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
Section(header: SettingsHeader(text: "Categories to Skip")) {
|
|
||||||
#if os(macOS)
|
|
||||||
let list = ForEach(SponsorBlockAPI.categories, id: \.self) { category in
|
|
||||||
SponsorBlockCategorySelectionRow(
|
|
||||||
title: SponsorBlockAPI.categoryDescription(category) ?? "Unknown",
|
|
||||||
selected: sponsorBlockCategories.contains(category)
|
|
||||||
) { value in
|
|
||||||
toggleCategory(category, value: value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Group {
|
|
||||||
if #available(macOS 12.0, *) {
|
|
||||||
list
|
|
||||||
.listStyle(.inset(alternatesRowBackgrounds: true))
|
|
||||||
} else {
|
|
||||||
list
|
|
||||||
.listStyle(.inset)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Spacer()
|
|
||||||
#else
|
|
||||||
ForEach(SponsorBlockAPI.categories, id: \.self) { category in
|
|
||||||
SponsorBlockCategorySelectionRow(
|
|
||||||
title: SponsorBlockAPI.categoryDescription(category) ?? "Unknown",
|
|
||||||
selected: sponsorBlockCategories.contains(category)
|
|
||||||
) { value in
|
|
||||||
toggleCategory(category, value: value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private var commentsInstancePicker: some View {
|
|
||||||
Picker("Source", selection: $commentsInstanceID) {
|
|
||||||
Text("Disabled").tag(Optional(""))
|
|
||||||
|
|
||||||
ForEach(InstancesModel.all.filter { $0.app.supportsComments }) { instance in
|
|
||||||
Text(instance.description).tag(Optional(instance.id))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.labelsHidden()
|
|
||||||
#if os(iOS)
|
|
||||||
.pickerStyle(.automatic)
|
|
||||||
#elseif os(tvOS)
|
|
||||||
.pickerStyle(.inline)
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !os(tvOS)
|
|
||||||
private var commentsPlacementPicker: some View {
|
|
||||||
Picker("Placement", selection: $commentsPlacement) {
|
|
||||||
Text("Below video description").tag(CommentsPlacement.info)
|
|
||||||
Text("Separate tab").tag(CommentsPlacement.separate)
|
|
||||||
}
|
|
||||||
.labelsHidden()
|
|
||||||
#if os(iOS)
|
|
||||||
.pickerStyle(.automatic)
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
func toggleCategory(_ category: String, value: Bool) {
|
|
||||||
if let index = sponsorBlockCategories.firstIndex(where: { $0 == category }), !value {
|
|
||||||
sponsorBlockCategories.remove(at: index)
|
|
||||||
} else if value {
|
|
||||||
sponsorBlockCategories.insert(category)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct SponsorBlockCategorySelectionRow: View {
|
|
||||||
let title: String
|
|
||||||
let selected: Bool
|
|
||||||
var action: (Bool) -> Void
|
|
||||||
|
|
||||||
@State private var toggleChecked = false
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
Button(action: { action(!selected) }) {
|
|
||||||
HStack {
|
|
||||||
#if os(macOS)
|
|
||||||
Toggle(isOn: $toggleChecked) {
|
|
||||||
Text(self.title)
|
|
||||||
Spacer()
|
|
||||||
}
|
|
||||||
.onAppear {
|
|
||||||
toggleChecked = selected
|
|
||||||
}
|
|
||||||
.onChange(of: toggleChecked) { new in
|
|
||||||
action(new)
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
Text(self.title)
|
|
||||||
Spacer()
|
|
||||||
if selected {
|
|
||||||
Image(systemName: "checkmark")
|
|
||||||
#if os(iOS)
|
|
||||||
.foregroundColor(.accentColor)
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
.contentShape(Rectangle())
|
|
||||||
}
|
|
||||||
#if !os(tvOS)
|
|
||||||
.buttonStyle(.plain)
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ServicesSettings_Previews: PreviewProvider {
|
|
||||||
static var previews: some View {
|
|
||||||
VStack {
|
|
||||||
ServicesSettings()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,13 +2,28 @@ import SwiftUI
|
|||||||
|
|
||||||
struct SettingsHeader: View {
|
struct SettingsHeader: View {
|
||||||
var text: String
|
var text: String
|
||||||
|
var secondary = false
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Text(text)
|
Group {
|
||||||
#if os(macOS) || os(tvOS)
|
#if os(iOS)
|
||||||
.font(.title3)
|
if secondary {
|
||||||
.foregroundColor(.secondary)
|
EmptyView()
|
||||||
.focusable(false)
|
} else {
|
||||||
|
Text(text)
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
Text(text)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#if os(tvOS)
|
||||||
|
.font(secondary ? .footnote : .title3)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
.focusable(false)
|
||||||
|
#endif
|
||||||
|
#if os(macOS)
|
||||||
|
.font(secondary ? .system(size: 13) : .system(size: 15))
|
||||||
|
.foregroundColor(secondary ? Color.primary : .secondary)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,10 @@ import SwiftUI
|
|||||||
struct SettingsView: View {
|
struct SettingsView: View {
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
private enum Tabs: Hashable {
|
private enum Tabs: Hashable {
|
||||||
case instances, browsing, history, playback, services, updates
|
case instances, browsing, player, history, sponsorBlock, updates, help
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@State private var selection = Tabs.instances
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@Environment(\.colorScheme) private var colorScheme
|
@Environment(\.colorScheme) private var colorScheme
|
||||||
@ -24,7 +26,7 @@ struct SettingsView: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
TabView {
|
TabView(selection: $selection) {
|
||||||
Form {
|
Form {
|
||||||
InstancesSettings()
|
InstancesSettings()
|
||||||
.environmentObject(accounts)
|
.environmentObject(accounts)
|
||||||
@ -42,6 +44,14 @@ struct SettingsView: View {
|
|||||||
}
|
}
|
||||||
.tag(Tabs.browsing)
|
.tag(Tabs.browsing)
|
||||||
|
|
||||||
|
Form {
|
||||||
|
PlayerSettings()
|
||||||
|
}
|
||||||
|
.tabItem {
|
||||||
|
Label("Player", systemImage: "play.rectangle")
|
||||||
|
}
|
||||||
|
.tag(Tabs.player)
|
||||||
|
|
||||||
Form {
|
Form {
|
||||||
HistorySettings()
|
HistorySettings()
|
||||||
}
|
}
|
||||||
@ -51,20 +61,12 @@ struct SettingsView: View {
|
|||||||
.tag(Tabs.history)
|
.tag(Tabs.history)
|
||||||
|
|
||||||
Form {
|
Form {
|
||||||
PlaybackSettings()
|
SponsorBlockSettings()
|
||||||
}
|
}
|
||||||
.tabItem {
|
.tabItem {
|
||||||
Label("Playback", systemImage: "play.rectangle")
|
Label("SponsorBlock", systemImage: "dollarsign.circle")
|
||||||
}
|
}
|
||||||
.tag(Tabs.playback)
|
.tag(Tabs.sponsorBlock)
|
||||||
|
|
||||||
Form {
|
|
||||||
ServicesSettings()
|
|
||||||
}
|
|
||||||
.tabItem {
|
|
||||||
Label("Services", systemImage: "puzzlepiece")
|
|
||||||
}
|
|
||||||
.tag(Tabs.services)
|
|
||||||
|
|
||||||
Form {
|
Form {
|
||||||
UpdatesSettings()
|
UpdatesSettings()
|
||||||
@ -73,20 +75,22 @@ struct SettingsView: View {
|
|||||||
Label("Updates", systemImage: "gearshape.2")
|
Label("Updates", systemImage: "gearshape.2")
|
||||||
}
|
}
|
||||||
.tag(Tabs.updates)
|
.tag(Tabs.updates)
|
||||||
|
|
||||||
|
Form {
|
||||||
|
Help()
|
||||||
|
}
|
||||||
|
.tabItem {
|
||||||
|
Label("Help", systemImage: "questionmark.circle")
|
||||||
|
}
|
||||||
|
.tag(Tabs.help)
|
||||||
}
|
}
|
||||||
.padding(20)
|
.padding(20)
|
||||||
.frame(width: 400, height: 400)
|
.frame(width: 480, height: windowHeight)
|
||||||
#else
|
#else
|
||||||
NavigationView {
|
NavigationView {
|
||||||
List {
|
List {
|
||||||
#if os(tvOS)
|
#if os(tvOS)
|
||||||
AccountSelectionView()
|
AccountSelectionView()
|
||||||
|
|
||||||
Section(header: SettingsHeader(text: "Favorites")) {
|
|
||||||
NavigationLink("Edit favorites...") {
|
|
||||||
EditFavorites()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Section(header: Text("Instances")) {
|
Section(header: Text("Instances")) {
|
||||||
@ -96,14 +100,55 @@ struct SettingsView: View {
|
|||||||
addInstanceButton
|
addInstanceButton
|
||||||
}
|
}
|
||||||
|
|
||||||
BrowsingSettings()
|
#if os(tvOS)
|
||||||
HistorySettings()
|
Divider()
|
||||||
PlaybackSettings()
|
#endif
|
||||||
ServicesSettings()
|
|
||||||
|
Section {
|
||||||
|
#if os(tvOS)
|
||||||
|
NavigationLink {
|
||||||
|
EditFavorites()
|
||||||
|
} label: {
|
||||||
|
Label("Favorites", systemImage: "heart.fill")
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
NavigationLink {
|
||||||
|
BrowsingSettings()
|
||||||
|
} label: {
|
||||||
|
Label("Browsing", systemImage: "list.and.film")
|
||||||
|
}
|
||||||
|
|
||||||
|
NavigationLink {
|
||||||
|
PlayerSettings()
|
||||||
|
} label: {
|
||||||
|
Label("Player", systemImage: "play.rectangle")
|
||||||
|
}
|
||||||
|
|
||||||
|
NavigationLink {
|
||||||
|
HistorySettings()
|
||||||
|
} label: {
|
||||||
|
Label("History", systemImage: "clock.arrow.circlepath")
|
||||||
|
}
|
||||||
|
|
||||||
|
NavigationLink {
|
||||||
|
SponsorBlockSettings()
|
||||||
|
} label: {
|
||||||
|
Label("SponsorBlock", systemImage: "dollarsign.circle")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Section(footer: versionString) {
|
||||||
|
NavigationLink {
|
||||||
|
Help()
|
||||||
|
} label: {
|
||||||
|
Label("Help", systemImage: "questionmark.circle")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.navigationTitle("Settings")
|
.navigationTitle("Settings")
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItem(placement: .navigationBarTrailing) {
|
ToolbarItem(placement: .navigationBarLeading) {
|
||||||
#if !os(tvOS)
|
#if !os(tvOS)
|
||||||
Button("Done") {
|
Button("Done") {
|
||||||
presentationMode.wrappedValue.dismiss()
|
presentationMode.wrappedValue.dismiss()
|
||||||
@ -126,9 +171,39 @@ struct SettingsView: View {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if os(macOS)
|
||||||
|
private var windowHeight: Double {
|
||||||
|
switch selection {
|
||||||
|
case .instances:
|
||||||
|
return 390
|
||||||
|
case .browsing:
|
||||||
|
return 350
|
||||||
|
case .player:
|
||||||
|
return 450
|
||||||
|
case .history:
|
||||||
|
return 480
|
||||||
|
case .sponsorBlock:
|
||||||
|
return 290
|
||||||
|
case .updates:
|
||||||
|
return 200
|
||||||
|
case .help:
|
||||||
|
return 570
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private var versionString: some View {
|
||||||
|
Text("Yattee \(YatteeApp.version) (build \(YatteeApp.build))")
|
||||||
|
#if os(tvOS)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
private var addInstanceButton: some View {
|
private var addInstanceButton: some View {
|
||||||
Button("Add Instance...") {
|
Button {
|
||||||
presentingInstanceForm = true
|
presentingInstanceForm = true
|
||||||
|
} label: {
|
||||||
|
Label("Add Instance...", systemImage: "plus")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
132
Shared/Settings/SponsorBlockSettings.swift
Normal file
132
Shared/Settings/SponsorBlockSettings.swift
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
import Defaults
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct SponsorBlockSettings: View {
|
||||||
|
@Default(.sponsorBlockInstance) private var sponsorBlockInstance
|
||||||
|
@Default(.sponsorBlockCategories) private var sponsorBlockCategories
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
Group {
|
||||||
|
#if os(macOS)
|
||||||
|
sections
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
#else
|
||||||
|
List {
|
||||||
|
sections
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#if os(tvOS)
|
||||||
|
.frame(maxWidth: 1000)
|
||||||
|
#elseif os(iOS)
|
||||||
|
.listStyle(.insetGrouped)
|
||||||
|
#endif
|
||||||
|
.navigationTitle("SponsorBlock")
|
||||||
|
}
|
||||||
|
|
||||||
|
private var sections: some View {
|
||||||
|
Group {
|
||||||
|
Section(header: SettingsHeader(text: "SponsorBlock API")) {
|
||||||
|
TextField(
|
||||||
|
"SponsorBlock API Instance",
|
||||||
|
text: $sponsorBlockInstance
|
||||||
|
)
|
||||||
|
.labelsHidden()
|
||||||
|
#if !os(macOS)
|
||||||
|
.autocapitalization(.none)
|
||||||
|
.keyboardType(.URL)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Section(header: SettingsHeader(text: "Categories to Skip")) {
|
||||||
|
#if os(macOS)
|
||||||
|
let list = ForEach(SponsorBlockAPI.categories, id: \.self) { category in
|
||||||
|
SponsorBlockCategorySelectionRow(
|
||||||
|
title: SponsorBlockAPI.categoryDescription(category) ?? "Unknown",
|
||||||
|
selected: sponsorBlockCategories.contains(category)
|
||||||
|
) { value in
|
||||||
|
toggleCategory(category, value: value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Group {
|
||||||
|
if #available(macOS 12.0, *) {
|
||||||
|
list
|
||||||
|
.listStyle(.inset(alternatesRowBackgrounds: true))
|
||||||
|
} else {
|
||||||
|
list
|
||||||
|
.listStyle(.inset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Spacer()
|
||||||
|
#else
|
||||||
|
ForEach(SponsorBlockAPI.categories, id: \.self) { category in
|
||||||
|
SponsorBlockCategorySelectionRow(
|
||||||
|
title: SponsorBlockAPI.categoryDescription(category) ?? "Unknown",
|
||||||
|
selected: sponsorBlockCategories.contains(category)
|
||||||
|
) { value in
|
||||||
|
toggleCategory(category, value: value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toggleCategory(_ category: String, value: Bool) {
|
||||||
|
if let index = sponsorBlockCategories.firstIndex(where: { $0 == category }), !value {
|
||||||
|
sponsorBlockCategories.remove(at: index)
|
||||||
|
} else if value {
|
||||||
|
sponsorBlockCategories.insert(category)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SponsorBlockCategorySelectionRow: View {
|
||||||
|
let title: String
|
||||||
|
let selected: Bool
|
||||||
|
var action: (Bool) -> Void
|
||||||
|
|
||||||
|
@State private var toggleChecked = false
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
Button(action: { action(!selected) }) {
|
||||||
|
HStack {
|
||||||
|
#if os(macOS)
|
||||||
|
Toggle(isOn: $toggleChecked) {
|
||||||
|
Text(self.title)
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.onAppear {
|
||||||
|
toggleChecked = selected
|
||||||
|
}
|
||||||
|
.onChange(of: toggleChecked) { new in
|
||||||
|
action(new)
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
Text(self.title)
|
||||||
|
Spacer()
|
||||||
|
if selected {
|
||||||
|
Image(systemName: "checkmark")
|
||||||
|
#if os(iOS)
|
||||||
|
.foregroundColor(.accentColor)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
.contentShape(Rectangle())
|
||||||
|
}
|
||||||
|
#if !os(tvOS)
|
||||||
|
.buttonStyle(.plain)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ServicesSettings_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
VStack {
|
||||||
|
SponsorBlockSettings()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,14 @@ import SwiftUI
|
|||||||
|
|
||||||
@main
|
@main
|
||||||
struct YatteeApp: App {
|
struct YatteeApp: App {
|
||||||
|
static var version: String {
|
||||||
|
Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "unknown"
|
||||||
|
}
|
||||||
|
|
||||||
|
static var build: String {
|
||||||
|
Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "unknown"
|
||||||
|
}
|
||||||
|
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
|
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
|
||||||
@StateObject private var updater = UpdaterModel()
|
@StateObject private var updater = UpdaterModel()
|
||||||
|
@ -99,6 +99,8 @@
|
|||||||
371F2F1C269B43D300E4A7AB /* NavigationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371F2F19269B43D300E4A7AB /* NavigationModel.swift */; };
|
371F2F1C269B43D300E4A7AB /* NavigationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371F2F19269B43D300E4A7AB /* NavigationModel.swift */; };
|
||||||
3722AEBC274DA396005EA4D6 /* Badge+Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3722AEBB274DA396005EA4D6 /* Badge+Backport.swift */; };
|
3722AEBC274DA396005EA4D6 /* Badge+Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3722AEBB274DA396005EA4D6 /* Badge+Backport.swift */; };
|
||||||
3722AEBE274DA401005EA4D6 /* Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3722AEBD274DA401005EA4D6 /* Backport.swift */; };
|
3722AEBE274DA401005EA4D6 /* Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3722AEBD274DA401005EA4D6 /* Backport.swift */; };
|
||||||
|
3727B74A27872A920021C15E /* VisualEffectBlur-iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3727B74927872A920021C15E /* VisualEffectBlur-iOS.swift */; };
|
||||||
|
3727B74B27872B880021C15E /* VisualEffectBlur-macOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3727B74727872A500021C15E /* VisualEffectBlur-macOS.swift */; };
|
||||||
3729037E2739E47400EA99F6 /* MenuCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3729037D2739E47400EA99F6 /* MenuCommands.swift */; };
|
3729037E2739E47400EA99F6 /* MenuCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3729037D2739E47400EA99F6 /* MenuCommands.swift */; };
|
||||||
3729037F2739E47400EA99F6 /* MenuCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3729037D2739E47400EA99F6 /* MenuCommands.swift */; };
|
3729037F2739E47400EA99F6 /* MenuCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3729037D2739E47400EA99F6 /* MenuCommands.swift */; };
|
||||||
372915E42687E33E00F5A35B /* Defaults in Frameworks */ = {isa = PBXBuildFile; productRef = 372915E32687E33E00F5A35B /* Defaults */; };
|
372915E42687E33E00F5A35B /* Defaults in Frameworks */ = {isa = PBXBuildFile; productRef = 372915E32687E33E00F5A35B /* Defaults */; };
|
||||||
@ -147,9 +149,9 @@
|
|||||||
3748186E26A769D60084E870 /* DetailBadge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3748186D26A769D60084E870 /* DetailBadge.swift */; };
|
3748186E26A769D60084E870 /* DetailBadge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3748186D26A769D60084E870 /* DetailBadge.swift */; };
|
||||||
3748186F26A769D60084E870 /* DetailBadge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3748186D26A769D60084E870 /* DetailBadge.swift */; };
|
3748186F26A769D60084E870 /* DetailBadge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3748186D26A769D60084E870 /* DetailBadge.swift */; };
|
||||||
3748187026A769D60084E870 /* DetailBadge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3748186D26A769D60084E870 /* DetailBadge.swift */; };
|
3748187026A769D60084E870 /* DetailBadge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3748186D26A769D60084E870 /* DetailBadge.swift */; };
|
||||||
37484C1926FC837400287258 /* PlaybackSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C1826FC837400287258 /* PlaybackSettings.swift */; };
|
37484C1926FC837400287258 /* PlayerSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C1826FC837400287258 /* PlayerSettings.swift */; };
|
||||||
37484C1A26FC837400287258 /* PlaybackSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C1826FC837400287258 /* PlaybackSettings.swift */; };
|
37484C1A26FC837400287258 /* PlayerSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C1826FC837400287258 /* PlayerSettings.swift */; };
|
||||||
37484C1B26FC837400287258 /* PlaybackSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C1826FC837400287258 /* PlaybackSettings.swift */; };
|
37484C1B26FC837400287258 /* PlayerSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C1826FC837400287258 /* PlayerSettings.swift */; };
|
||||||
37484C2526FC83E000287258 /* InstanceForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C2426FC83E000287258 /* InstanceForm.swift */; };
|
37484C2526FC83E000287258 /* InstanceForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C2426FC83E000287258 /* InstanceForm.swift */; };
|
||||||
37484C2626FC83E000287258 /* InstanceForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C2426FC83E000287258 /* InstanceForm.swift */; };
|
37484C2626FC83E000287258 /* InstanceForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C2426FC83E000287258 /* InstanceForm.swift */; };
|
||||||
37484C2726FC83E000287258 /* InstanceForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C2426FC83E000287258 /* InstanceForm.swift */; };
|
37484C2726FC83E000287258 /* InstanceForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C2426FC83E000287258 /* InstanceForm.swift */; };
|
||||||
@ -161,9 +163,9 @@
|
|||||||
37484C3126FCB8F900287258 /* AccountValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C3026FCB8F900287258 /* AccountValidator.swift */; };
|
37484C3126FCB8F900287258 /* AccountValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C3026FCB8F900287258 /* AccountValidator.swift */; };
|
||||||
37484C3226FCB8F900287258 /* AccountValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C3026FCB8F900287258 /* AccountValidator.swift */; };
|
37484C3226FCB8F900287258 /* AccountValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C3026FCB8F900287258 /* AccountValidator.swift */; };
|
||||||
37484C3326FCB8F900287258 /* AccountValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C3026FCB8F900287258 /* AccountValidator.swift */; };
|
37484C3326FCB8F900287258 /* AccountValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C3026FCB8F900287258 /* AccountValidator.swift */; };
|
||||||
374C053527242D9F009BDDBE /* ServicesSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374C053427242D9F009BDDBE /* ServicesSettings.swift */; };
|
374C053527242D9F009BDDBE /* SponsorBlockSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374C053427242D9F009BDDBE /* SponsorBlockSettings.swift */; };
|
||||||
374C053627242D9F009BDDBE /* ServicesSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374C053427242D9F009BDDBE /* ServicesSettings.swift */; };
|
374C053627242D9F009BDDBE /* SponsorBlockSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374C053427242D9F009BDDBE /* SponsorBlockSettings.swift */; };
|
||||||
374C053727242D9F009BDDBE /* ServicesSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374C053427242D9F009BDDBE /* ServicesSettings.swift */; };
|
374C053727242D9F009BDDBE /* SponsorBlockSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374C053427242D9F009BDDBE /* SponsorBlockSettings.swift */; };
|
||||||
374C053B2724614F009BDDBE /* PlayerTVMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374C053A2724614F009BDDBE /* PlayerTVMenu.swift */; };
|
374C053B2724614F009BDDBE /* PlayerTVMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374C053A2724614F009BDDBE /* PlayerTVMenu.swift */; };
|
||||||
374C053C2724614F009BDDBE /* PlayerTVMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374C053A2724614F009BDDBE /* PlayerTVMenu.swift */; };
|
374C053C2724614F009BDDBE /* PlayerTVMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374C053A2724614F009BDDBE /* PlayerTVMenu.swift */; };
|
||||||
374C053D2724614F009BDDBE /* PlayerTVMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374C053A2724614F009BDDBE /* PlayerTVMenu.swift */; };
|
374C053D2724614F009BDDBE /* PlayerTVMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374C053A2724614F009BDDBE /* PlayerTVMenu.swift */; };
|
||||||
@ -177,6 +179,9 @@
|
|||||||
3751B4B227836902000B7DF4 /* SearchPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3751B4B127836902000B7DF4 /* SearchPage.swift */; };
|
3751B4B227836902000B7DF4 /* SearchPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3751B4B127836902000B7DF4 /* SearchPage.swift */; };
|
||||||
3751B4B327836902000B7DF4 /* SearchPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3751B4B127836902000B7DF4 /* SearchPage.swift */; };
|
3751B4B327836902000B7DF4 /* SearchPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3751B4B127836902000B7DF4 /* SearchPage.swift */; };
|
||||||
3751B4B427836902000B7DF4 /* SearchPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3751B4B127836902000B7DF4 /* SearchPage.swift */; };
|
3751B4B427836902000B7DF4 /* SearchPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3751B4B127836902000B7DF4 /* SearchPage.swift */; };
|
||||||
|
37579D5D27864F5F00FD0B98 /* Help.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37579D5C27864F5F00FD0B98 /* Help.swift */; };
|
||||||
|
37579D5E27864F5F00FD0B98 /* Help.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37579D5C27864F5F00FD0B98 /* Help.swift */; };
|
||||||
|
37579D5F27864F5F00FD0B98 /* Help.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37579D5C27864F5F00FD0B98 /* Help.swift */; };
|
||||||
3758638A2721B0A9000CB14E /* ChannelCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3743B86727216D3600261544 /* ChannelCell.swift */; };
|
3758638A2721B0A9000CB14E /* ChannelCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3743B86727216D3600261544 /* ChannelCell.swift */; };
|
||||||
37599F30272B42810087F250 /* FavoriteItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37599F2F272B42810087F250 /* FavoriteItem.swift */; };
|
37599F30272B42810087F250 /* FavoriteItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37599F2F272B42810087F250 /* FavoriteItem.swift */; };
|
||||||
37599F31272B42810087F250 /* FavoriteItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37599F2F272B42810087F250 /* FavoriteItem.swift */; };
|
37599F31272B42810087F250 /* FavoriteItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37599F2F272B42810087F250 /* FavoriteItem.swift */; };
|
||||||
@ -633,6 +638,8 @@
|
|||||||
3722AEBB274DA396005EA4D6 /* Badge+Backport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Badge+Backport.swift"; sourceTree = "<group>"; };
|
3722AEBB274DA396005EA4D6 /* Badge+Backport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Badge+Backport.swift"; sourceTree = "<group>"; };
|
||||||
3722AEBD274DA401005EA4D6 /* Backport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Backport.swift; sourceTree = "<group>"; };
|
3722AEBD274DA401005EA4D6 /* Backport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Backport.swift; sourceTree = "<group>"; };
|
||||||
3722AEBF274DAEB8005EA4D6 /* Tint+Backport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Tint+Backport.swift"; sourceTree = "<group>"; };
|
3722AEBF274DAEB8005EA4D6 /* Tint+Backport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Tint+Backport.swift"; sourceTree = "<group>"; };
|
||||||
|
3727B74727872A500021C15E /* VisualEffectBlur-macOS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VisualEffectBlur-macOS.swift"; sourceTree = "<group>"; };
|
||||||
|
3727B74927872A920021C15E /* VisualEffectBlur-iOS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VisualEffectBlur-iOS.swift"; sourceTree = "<group>"; };
|
||||||
3729037D2739E47400EA99F6 /* MenuCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuCommands.swift; sourceTree = "<group>"; };
|
3729037D2739E47400EA99F6 /* MenuCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuCommands.swift; sourceTree = "<group>"; };
|
||||||
372915E52687E3B900F5A35B /* Defaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Defaults.swift; sourceTree = "<group>"; };
|
372915E52687E3B900F5A35B /* Defaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Defaults.swift; sourceTree = "<group>"; };
|
||||||
3730D89F2712E2B70020ED53 /* NowPlayingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NowPlayingView.swift; sourceTree = "<group>"; };
|
3730D89F2712E2B70020ED53 /* NowPlayingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NowPlayingView.swift; sourceTree = "<group>"; };
|
||||||
@ -651,18 +658,19 @@
|
|||||||
3748186526A7627F0084E870 /* Video+Fixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Video+Fixtures.swift"; sourceTree = "<group>"; };
|
3748186526A7627F0084E870 /* Video+Fixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Video+Fixtures.swift"; sourceTree = "<group>"; };
|
||||||
3748186926A764FB0084E870 /* Thumbnail+Fixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Thumbnail+Fixtures.swift"; sourceTree = "<group>"; };
|
3748186926A764FB0084E870 /* Thumbnail+Fixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Thumbnail+Fixtures.swift"; sourceTree = "<group>"; };
|
||||||
3748186D26A769D60084E870 /* DetailBadge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailBadge.swift; sourceTree = "<group>"; };
|
3748186D26A769D60084E870 /* DetailBadge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailBadge.swift; sourceTree = "<group>"; };
|
||||||
37484C1826FC837400287258 /* PlaybackSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaybackSettings.swift; sourceTree = "<group>"; };
|
37484C1826FC837400287258 /* PlayerSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerSettings.swift; sourceTree = "<group>"; };
|
||||||
37484C2426FC83E000287258 /* InstanceForm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceForm.swift; sourceTree = "<group>"; };
|
37484C2426FC83E000287258 /* InstanceForm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceForm.swift; sourceTree = "<group>"; };
|
||||||
37484C2826FC83FF00287258 /* AccountForm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountForm.swift; sourceTree = "<group>"; };
|
37484C2826FC83FF00287258 /* AccountForm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountForm.swift; sourceTree = "<group>"; };
|
||||||
37484C2C26FC844700287258 /* InstanceSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceSettings.swift; sourceTree = "<group>"; };
|
37484C2C26FC844700287258 /* InstanceSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceSettings.swift; sourceTree = "<group>"; };
|
||||||
37484C3026FCB8F900287258 /* AccountValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountValidator.swift; sourceTree = "<group>"; };
|
37484C3026FCB8F900287258 /* AccountValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountValidator.swift; sourceTree = "<group>"; };
|
||||||
374C053427242D9F009BDDBE /* ServicesSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServicesSettings.swift; sourceTree = "<group>"; };
|
374C053427242D9F009BDDBE /* SponsorBlockSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SponsorBlockSettings.swift; sourceTree = "<group>"; };
|
||||||
374C053A2724614F009BDDBE /* PlayerTVMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerTVMenu.swift; sourceTree = "<group>"; };
|
374C053A2724614F009BDDBE /* PlayerTVMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerTVMenu.swift; sourceTree = "<group>"; };
|
||||||
374C053E272472C0009BDDBE /* PlayerSponsorBlock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerSponsorBlock.swift; sourceTree = "<group>"; };
|
374C053E272472C0009BDDBE /* PlayerSponsorBlock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerSponsorBlock.swift; sourceTree = "<group>"; };
|
||||||
374C0542272496E4009BDDBE /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = macOS/AppDelegate.swift; sourceTree = SOURCE_ROOT; };
|
374C0542272496E4009BDDBE /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = macOS/AppDelegate.swift; sourceTree = SOURCE_ROOT; };
|
||||||
374C0544272496FD009BDDBE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
374C0544272496FD009BDDBE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
375168D52700FAFF008F96A6 /* Debounce.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Debounce.swift; sourceTree = "<group>"; };
|
375168D52700FAFF008F96A6 /* Debounce.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Debounce.swift; sourceTree = "<group>"; };
|
||||||
3751B4B127836902000B7DF4 /* SearchPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchPage.swift; sourceTree = "<group>"; };
|
3751B4B127836902000B7DF4 /* SearchPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchPage.swift; sourceTree = "<group>"; };
|
||||||
|
37579D5C27864F5F00FD0B98 /* Help.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Help.swift; sourceTree = "<group>"; };
|
||||||
37599F2F272B42810087F250 /* FavoriteItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoriteItem.swift; sourceTree = "<group>"; };
|
37599F2F272B42810087F250 /* FavoriteItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoriteItem.swift; sourceTree = "<group>"; };
|
||||||
37599F33272B44000087F250 /* FavoritesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoritesModel.swift; sourceTree = "<group>"; };
|
37599F33272B44000087F250 /* FavoritesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoritesModel.swift; sourceTree = "<group>"; };
|
||||||
37599F37272B4D740087F250 /* FavoriteButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoriteButton.swift; sourceTree = "<group>"; };
|
37599F37272B4D740087F250 /* FavoriteButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoriteButton.swift; sourceTree = "<group>"; };
|
||||||
@ -1003,6 +1011,8 @@
|
|||||||
3722AEBD274DA401005EA4D6 /* Backport.swift */,
|
3722AEBD274DA401005EA4D6 /* Backport.swift */,
|
||||||
3722AEBB274DA396005EA4D6 /* Badge+Backport.swift */,
|
3722AEBB274DA396005EA4D6 /* Badge+Backport.swift */,
|
||||||
3722AEBF274DAEB8005EA4D6 /* Tint+Backport.swift */,
|
3722AEBF274DAEB8005EA4D6 /* Tint+Backport.swift */,
|
||||||
|
3727B74727872A500021C15E /* VisualEffectBlur-macOS.swift */,
|
||||||
|
3727B74927872A920021C15E /* VisualEffectBlur-iOS.swift */,
|
||||||
);
|
);
|
||||||
path = Backports;
|
path = Backports;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -1068,11 +1078,12 @@
|
|||||||
37E084AB2753D95F00039B7D /* AccountsNavigationLink.swift */,
|
37E084AB2753D95F00039B7D /* AccountsNavigationLink.swift */,
|
||||||
37732FEF2703A26300F04329 /* AccountValidationStatus.swift */,
|
37732FEF2703A26300F04329 /* AccountValidationStatus.swift */,
|
||||||
376BE50A27349108009AD608 /* BrowsingSettings.swift */,
|
376BE50A27349108009AD608 /* BrowsingSettings.swift */,
|
||||||
|
37579D5C27864F5F00FD0B98 /* Help.swift */,
|
||||||
37BC50A72778A84700510953 /* HistorySettings.swift */,
|
37BC50A72778A84700510953 /* HistorySettings.swift */,
|
||||||
37484C2426FC83E000287258 /* InstanceForm.swift */,
|
37484C2426FC83E000287258 /* InstanceForm.swift */,
|
||||||
37484C2C26FC844700287258 /* InstanceSettings.swift */,
|
37484C2C26FC844700287258 /* InstanceSettings.swift */,
|
||||||
37484C1826FC837400287258 /* PlaybackSettings.swift */,
|
37484C1826FC837400287258 /* PlayerSettings.swift */,
|
||||||
374C053427242D9F009BDDBE /* ServicesSettings.swift */,
|
374C053427242D9F009BDDBE /* SponsorBlockSettings.swift */,
|
||||||
376BE50627347B57009AD608 /* SettingsHeader.swift */,
|
376BE50627347B57009AD608 /* SettingsHeader.swift */,
|
||||||
37B044B626F7AB9000E1419D /* SettingsView.swift */,
|
37B044B626F7AB9000E1419D /* SettingsView.swift */,
|
||||||
);
|
);
|
||||||
@ -1903,13 +1914,14 @@
|
|||||||
378E50FF26FE8EEE00F49626 /* AccountsMenuView.swift in Sources */,
|
378E50FF26FE8EEE00F49626 /* AccountsMenuView.swift in Sources */,
|
||||||
37169AA62729E2CC0011DE61 /* AccountsBridge.swift in Sources */,
|
37169AA62729E2CC0011DE61 /* AccountsBridge.swift in Sources */,
|
||||||
37C7A1DA267CACF50010EAD6 /* TrendingCountry.swift in Sources */,
|
37C7A1DA267CACF50010EAD6 /* TrendingCountry.swift in Sources */,
|
||||||
|
3727B74A27872A920021C15E /* VisualEffectBlur-iOS.swift in Sources */,
|
||||||
37977583268922F600DD52A8 /* InvidiousAPI.swift in Sources */,
|
37977583268922F600DD52A8 /* InvidiousAPI.swift in Sources */,
|
||||||
37130A5F277657300033018A /* PersistenceController.swift in Sources */,
|
37130A5F277657300033018A /* PersistenceController.swift in Sources */,
|
||||||
37FD43E32704847C0073EE42 /* View+Fixtures.swift in Sources */,
|
37FD43E32704847C0073EE42 /* View+Fixtures.swift in Sources */,
|
||||||
37BE0BD626A1D4A90092E2DB /* PlayerViewController.swift in Sources */,
|
37BE0BD626A1D4A90092E2DB /* PlayerViewController.swift in Sources */,
|
||||||
37BA793F26DB8F97002A0235 /* ChannelVideosView.swift in Sources */,
|
37BA793F26DB8F97002A0235 /* ChannelVideosView.swift in Sources */,
|
||||||
37C194C726F6A9C8005D3B96 /* RecentsModel.swift in Sources */,
|
37C194C726F6A9C8005D3B96 /* RecentsModel.swift in Sources */,
|
||||||
37484C1926FC837400287258 /* PlaybackSettings.swift in Sources */,
|
37484C1926FC837400287258 /* PlayerSettings.swift in Sources */,
|
||||||
3711403F26B206A6005B3555 /* SearchModel.swift in Sources */,
|
3711403F26B206A6005B3555 /* SearchModel.swift in Sources */,
|
||||||
3729037E2739E47400EA99F6 /* MenuCommands.swift in Sources */,
|
3729037E2739E47400EA99F6 /* MenuCommands.swift in Sources */,
|
||||||
37F64FE426FE70A60081B69E /* RedrawOnModifier.swift in Sources */,
|
37F64FE426FE70A60081B69E /* RedrawOnModifier.swift in Sources */,
|
||||||
@ -1958,7 +1970,7 @@
|
|||||||
377FC7E3267A084A00A6BBAF /* VideoCell.swift in Sources */,
|
377FC7E3267A084A00A6BBAF /* VideoCell.swift in Sources */,
|
||||||
37C3A251272366440087A57A /* ChannelPlaylistView.swift in Sources */,
|
37C3A251272366440087A57A /* ChannelPlaylistView.swift in Sources */,
|
||||||
37E2EEAB270656EC00170416 /* PlayerControlsView.swift in Sources */,
|
37E2EEAB270656EC00170416 /* PlayerControlsView.swift in Sources */,
|
||||||
374C053527242D9F009BDDBE /* ServicesSettings.swift in Sources */,
|
374C053527242D9F009BDDBE /* SponsorBlockSettings.swift in Sources */,
|
||||||
37BF661C27308859008CCFB0 /* DropFavorite.swift in Sources */,
|
37BF661C27308859008CCFB0 /* DropFavorite.swift in Sources */,
|
||||||
376A33E42720CB35000C1D6B /* Account.swift in Sources */,
|
376A33E42720CB35000C1D6B /* Account.swift in Sources */,
|
||||||
37BA794326DBA973002A0235 /* PlaylistsModel.swift in Sources */,
|
37BA794326DBA973002A0235 /* PlaylistsModel.swift in Sources */,
|
||||||
@ -2022,6 +2034,7 @@
|
|||||||
371F2F1A269B43D300E4A7AB /* NavigationModel.swift in Sources */,
|
371F2F1A269B43D300E4A7AB /* NavigationModel.swift in Sources */,
|
||||||
37BE0BCF26A0E2D50092E2DB /* VideoPlayerView.swift in Sources */,
|
37BE0BCF26A0E2D50092E2DB /* VideoPlayerView.swift in Sources */,
|
||||||
3769C02E2779F18600DDB3EA /* PlaceholderProgressView.swift in Sources */,
|
3769C02E2779F18600DDB3EA /* PlaceholderProgressView.swift in Sources */,
|
||||||
|
37579D5D27864F5F00FD0B98 /* Help.swift in Sources */,
|
||||||
3758638A2721B0A9000CB14E /* ChannelCell.swift in Sources */,
|
3758638A2721B0A9000CB14E /* ChannelCell.swift in Sources */,
|
||||||
37001563271B1F250049C794 /* AccountsModel.swift in Sources */,
|
37001563271B1F250049C794 /* AccountsModel.swift in Sources */,
|
||||||
37CC3F50270D010D00608308 /* VideoBanner.swift in Sources */,
|
37CC3F50270D010D00608308 /* VideoBanner.swift in Sources */,
|
||||||
@ -2043,6 +2056,7 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
3727B74B27872B880021C15E /* VisualEffectBlur-macOS.swift in Sources */,
|
||||||
374710062755291C00CE0F87 /* SearchField.swift in Sources */,
|
374710062755291C00CE0F87 /* SearchField.swift in Sources */,
|
||||||
378AE93F274EDFB5006A4EE1 /* Tint+Backport.swift in Sources */,
|
378AE93F274EDFB5006A4EE1 /* Tint+Backport.swift in Sources */,
|
||||||
37C194C826F6A9C8005D3B96 /* RecentsModel.swift in Sources */,
|
37C194C826F6A9C8005D3B96 /* RecentsModel.swift in Sources */,
|
||||||
@ -2053,7 +2067,7 @@
|
|||||||
37C3A24627235DA70087A57A /* ChannelPlaylist.swift in Sources */,
|
37C3A24627235DA70087A57A /* ChannelPlaylist.swift in Sources */,
|
||||||
37CEE4BE2677B670005A1EFE /* SingleAssetStream.swift in Sources */,
|
37CEE4BE2677B670005A1EFE /* SingleAssetStream.swift in Sources */,
|
||||||
374C0540272472C0009BDDBE /* PlayerSponsorBlock.swift in Sources */,
|
374C0540272472C0009BDDBE /* PlayerSponsorBlock.swift in Sources */,
|
||||||
374C053627242D9F009BDDBE /* ServicesSettings.swift in Sources */,
|
374C053627242D9F009BDDBE /* SponsorBlockSettings.swift in Sources */,
|
||||||
37BA794826DC2E56002A0235 /* AppSidebarSubscriptions.swift in Sources */,
|
37BA794826DC2E56002A0235 /* AppSidebarSubscriptions.swift in Sources */,
|
||||||
37E70928271CDDAE00D34DDE /* OpenSettingsButton.swift in Sources */,
|
37E70928271CDDAE00D34DDE /* OpenSettingsButton.swift in Sources */,
|
||||||
37DD9DA42785BBC900539416 /* NoCommentsView.swift in Sources */,
|
37DD9DA42785BBC900539416 /* NoCommentsView.swift in Sources */,
|
||||||
@ -2080,7 +2094,7 @@
|
|||||||
376B2E0826F920D600B1D64D /* SignInRequiredView.swift in Sources */,
|
376B2E0826F920D600B1D64D /* SignInRequiredView.swift in Sources */,
|
||||||
37CC3F4D270CFE1700608308 /* PlayerQueueView.swift in Sources */,
|
37CC3F4D270CFE1700608308 /* PlayerQueueView.swift in Sources */,
|
||||||
37B81B0026D2CA3700675966 /* VideoDetails.swift in Sources */,
|
37B81B0026D2CA3700675966 /* VideoDetails.swift in Sources */,
|
||||||
37484C1A26FC837400287258 /* PlaybackSettings.swift in Sources */,
|
37484C1A26FC837400287258 /* PlayerSettings.swift in Sources */,
|
||||||
37BD07C32698AD4F003EBB87 /* ContentView.swift in Sources */,
|
37BD07C32698AD4F003EBB87 /* ContentView.swift in Sources */,
|
||||||
37484C3226FCB8F900287258 /* AccountValidator.swift in Sources */,
|
37484C3226FCB8F900287258 /* AccountValidator.swift in Sources */,
|
||||||
378AE944274EF00A006A4EE1 /* Color+Background.swift in Sources */,
|
378AE944274EF00A006A4EE1 /* Color+Background.swift in Sources */,
|
||||||
@ -2117,6 +2131,7 @@
|
|||||||
37AAF29126740715007FC770 /* Channel.swift in Sources */,
|
37AAF29126740715007FC770 /* Channel.swift in Sources */,
|
||||||
376A33E12720CAD6000C1D6B /* VideosApp.swift in Sources */,
|
376A33E12720CAD6000C1D6B /* VideosApp.swift in Sources */,
|
||||||
37BD07BC2698AB60003EBB87 /* AppSidebarNavigation.swift in Sources */,
|
37BD07BC2698AB60003EBB87 /* AppSidebarNavigation.swift in Sources */,
|
||||||
|
37579D5E27864F5F00FD0B98 /* Help.swift in Sources */,
|
||||||
37EF9A77275BEB8E0043B585 /* CommentView.swift in Sources */,
|
37EF9A77275BEB8E0043B585 /* CommentView.swift in Sources */,
|
||||||
37BF661D27308859008CCFB0 /* DropFavorite.swift in Sources */,
|
37BF661D27308859008CCFB0 /* DropFavorite.swift in Sources */,
|
||||||
3748186F26A769D60084E870 /* DetailBadge.swift in Sources */,
|
3748186F26A769D60084E870 /* DetailBadge.swift in Sources */,
|
||||||
@ -2273,6 +2288,7 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
37579D5F27864F5F00FD0B98 /* Help.swift in Sources */,
|
||||||
37EAD871267B9ED100D9E01B /* Segment.swift in Sources */,
|
37EAD871267B9ED100D9E01B /* Segment.swift in Sources */,
|
||||||
373C8FE6275B955100CB5936 /* CommentsPage.swift in Sources */,
|
373C8FE6275B955100CB5936 /* CommentsPage.swift in Sources */,
|
||||||
37DD9DBC2785D60300539416 /* FramePreferenceKey.swift in Sources */,
|
37DD9DBC2785D60300539416 /* FramePreferenceKey.swift in Sources */,
|
||||||
@ -2365,7 +2381,7 @@
|
|||||||
37B2631C2735EAAB00FE0D40 /* FavoriteResourceObserver.swift in Sources */,
|
37B2631C2735EAAB00FE0D40 /* FavoriteResourceObserver.swift in Sources */,
|
||||||
37484C2B26FC83FF00287258 /* AccountForm.swift in Sources */,
|
37484C2B26FC83FF00287258 /* AccountForm.swift in Sources */,
|
||||||
37FB2860272225E800A57617 /* ContentItemView.swift in Sources */,
|
37FB2860272225E800A57617 /* ContentItemView.swift in Sources */,
|
||||||
374C053727242D9F009BDDBE /* ServicesSettings.swift in Sources */,
|
374C053727242D9F009BDDBE /* SponsorBlockSettings.swift in Sources */,
|
||||||
37C069802725C8D400F7F6CB /* CMTime+DefaultTimescale.swift in Sources */,
|
37C069802725C8D400F7F6CB /* CMTime+DefaultTimescale.swift in Sources */,
|
||||||
3711404126B206A6005B3555 /* SearchModel.swift in Sources */,
|
3711404126B206A6005B3555 /* SearchModel.swift in Sources */,
|
||||||
37FD43F02704A9C00073EE42 /* RecentsModel.swift in Sources */,
|
37FD43F02704A9C00073EE42 /* RecentsModel.swift in Sources */,
|
||||||
@ -2398,7 +2414,7 @@
|
|||||||
37C3A24F272360470087A57A /* ChannelPlaylist+Fixtures.swift in Sources */,
|
37C3A24F272360470087A57A /* ChannelPlaylist+Fixtures.swift in Sources */,
|
||||||
37FB28432721B22200A57617 /* ContentItem.swift in Sources */,
|
37FB28432721B22200A57617 /* ContentItem.swift in Sources */,
|
||||||
37AAF2A226741C97007FC770 /* SubscriptionsView.swift in Sources */,
|
37AAF2A226741C97007FC770 /* SubscriptionsView.swift in Sources */,
|
||||||
37484C1B26FC837400287258 /* PlaybackSettings.swift in Sources */,
|
37484C1B26FC837400287258 /* PlayerSettings.swift in Sources */,
|
||||||
372915E82687E3B900F5A35B /* Defaults.swift in Sources */,
|
372915E82687E3B900F5A35B /* Defaults.swift in Sources */,
|
||||||
37BAB54C269B39FD00E75ED1 /* TVNavigationView.swift in Sources */,
|
37BAB54C269B39FD00E75ED1 /* TVNavigationView.swift in Sources */,
|
||||||
3797758D2689345500DD52A8 /* Store.swift in Sources */,
|
3797758D2689345500DD52A8 /* Store.swift in Sources */,
|
||||||
|
@ -22,6 +22,9 @@ struct UpdatesSettings: View {
|
|||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
|
Text("Yattee \(YatteeApp.version) (build \(YatteeApp.build))")
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
|
||||||
CheckForUpdatesView()
|
CheckForUpdatesView()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ struct AccountSelectionView: View {
|
|||||||
@Default(.instances) private var instances
|
@Default(.instances) private var instances
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Section(header: SettingsHeader(text: showHeader ? "Current Account" : "")) {
|
Section(header: Text(showHeader ? "Current Account" : "")) {
|
||||||
Button(accountButtonTitle(account: accountsModel.current, long: true)) {
|
Button(accountButtonTitle(account: accountsModel.current, long: true)) {
|
||||||
if let account = nextAccount {
|
if let account = nextAccount {
|
||||||
accountsModel.setCurrent(account)
|
accountsModel.setCurrent(account)
|
||||||
|
@ -71,7 +71,7 @@ struct EditFavorites: View {
|
|||||||
}
|
}
|
||||||
.frame(width: 1000, alignment: .leading)
|
.frame(width: 1000, alignment: .leading)
|
||||||
}
|
}
|
||||||
.navigationTitle("Edit Favorites")
|
.navigationTitle("Favorites")
|
||||||
}
|
}
|
||||||
|
|
||||||
func label(_ item: FavoriteItem) -> String {
|
func label(_ item: FavoriteItem) -> String {
|
||||||
|
Loading…
Reference in New Issue
Block a user