Home Settings

This commit is contained in:
Arkadiusz Fal
2023-05-25 14:28:29 +02:00
parent 12afb31c03
commit 0061bd8c20
26 changed files with 911 additions and 396 deletions

View File

@@ -9,19 +9,13 @@ struct BrowsingSettings: View {
@Default(.accountPickerDisplaysAnonymousAccounts) private var accountPickerDisplaysAnonymousAccounts
@Default(.showUnwatchedFeedBadges) private var showUnwatchedFeedBadges
#if os(iOS)
@Default(.homeRecentDocumentsItems) private var homeRecentDocumentsItems
@Default(.lockPortraitWhenBrowsing) private var lockPortraitWhenBrowsing
@Default(.showDocuments) private var showDocuments
#endif
@Default(.thumbnailsQuality) private var thumbnailsQuality
@Default(.channelOnThumbnail) private var channelOnThumbnail
@Default(.timeOnThumbnail) private var timeOnThumbnail
@Default(.showHome) private var showHome
@Default(.showFavoritesInHome) private var showFavoritesInHome
@Default(.showQueueInHome) private var showQueueInHome
@Default(.showOpenActionsInHome) private var showOpenActionsInHome
@Default(.showOpenActionsToolbarItem) private var showOpenActionsToolbarItem
@Default(.homeHistoryItems) private var homeHistoryItems
@Default(.visibleSections) private var visibleSections
@Default(.playerButtonSingleTapGesture) private var playerButtonSingleTapGesture
@Default(.playerButtonDoubleTapGesture) private var playerButtonDoubleTapGesture
@@ -32,12 +26,11 @@ struct BrowsingSettings: View {
@ObservedObject private var accounts = AccountsModel.shared
@State private var homeHistoryItemsText = ""
#if os(iOS)
@State private var homeRecentDocumentsItemsText = ""
#endif
#if os(macOS)
@State private var presentingEditFavoritesSheet = false
@State private var presentingHomeSettingsSheet = false
#endif
var body: some View {
@@ -83,79 +76,32 @@ struct BrowsingSettings: View {
}
}
private var homeSettings: some View {
Section(header: SettingsHeader(text: "Home".localized())) {
#if !os(tvOS)
if !accounts.isEmpty {
Toggle("Show Home", isOn: $showHome)
}
#endif
Toggle("Show Open Videos quick actions", isOn: $showOpenActionsInHome)
Toggle("Show Next in Queue", isOn: $showQueueInHome)
#if os(iOS)
HStack {
Text("Recent Documents")
TextField("Recent Documents", text: $homeRecentDocumentsItemsText)
.multilineTextAlignment(.trailing)
.labelsHidden()
#if !os(macOS)
.keyboardType(.numberPad)
#endif
.onAppear {
homeRecentDocumentsItemsText = String(homeRecentDocumentsItems)
}
.onChange(of: homeRecentDocumentsItemsText) { newValue in
homeRecentDocumentsItems = Int(newValue) ?? 3
}
}
#endif
HStack {
Text("Recent History")
TextField("Recent History", text: $homeHistoryItemsText)
.multilineTextAlignment(.trailing)
.labelsHidden()
#if !os(macOS)
.keyboardType(.numberPad)
#endif
.onAppear {
homeHistoryItemsText = String(homeHistoryItems)
@ViewBuilder private var homeSettings: some View {
if !accounts.isEmpty {
Section(header: SettingsHeader(text: "Home".localized())) {
#if os(macOS)
Button {
presentingHomeSettingsSheet = true
} label: {
Text("Home Settings")
}
.onChange(of: homeHistoryItemsText) { newValue in
homeHistoryItems = Int(newValue) ?? 10
}
}
if !accounts.isEmpty {
Toggle("Show Favorites", isOn: $showFavoritesInHome)
Group {
#if os(macOS)
Button {
presentingEditFavoritesSheet = true
} label: {
Text("Edit Favorites…")
}
.sheet(isPresented: $presentingEditFavoritesSheet) {
VStack(alignment: .leading) {
Button("Done") {
presentingEditFavoritesSheet = false
}
.padding()
.keyboardShortcut(.cancelAction)
EditFavorites()
.sheet(isPresented: $presentingHomeSettingsSheet) {
VStack(alignment: .leading) {
Button("Done") {
presentingHomeSettingsSheet = false
}
.frame(width: 500, height: 300)
.padding()
.keyboardShortcut(.cancelAction)
HomeSettings()
}
#else
NavigationLink(destination: LazyView(EditFavorites())) {
Text("Edit Favorites…")
}
#endif
}
.disabled(!showFavoritesInHome)
.frame(width: 500, height: 800)
}
#else
NavigationLink(destination: LazyView(HomeSettings())) {
Text("Home Settings")
}
#endif
}
}
}

View File

@@ -1,119 +0,0 @@
import Defaults
import SwiftUI
struct EditFavorites: View {
private var playlistsModel = PlaylistsModel.shared
private var model = FavoritesModel.shared
@Default(.favorites) private var favorites
var body: some View {
Group {
#if os(tvOS)
ScrollView {
VStack {
editor
}
}
.frame(width: 1000)
#else
List {
editor
}
#endif
}
.navigationTitle("Favorites")
}
var editor: some View {
Group {
Section(header: Text("Favorites")) {
if favorites.isEmpty {
Text("Favorites is empty")
.foregroundColor(.secondary)
}
ForEach(favorites) { item in
HStack {
Text(label(item))
Spacer()
HStack(spacing: 30) {
Button {
model.moveUp(item)
} label: {
Label("Move Up", systemImage: "arrow.up")
}
Button {
model.moveDown(item)
} label: {
Label("Move Down", systemImage: "arrow.down")
}
Button {
model.remove(item)
} label: {
Label("Remove", systemImage: "trash")
}
}
#if !os(tvOS)
.buttonStyle(.borderless)
#endif
}
}
}
#if os(tvOS)
.padding(.trailing, 40)
#endif
#if os(tvOS)
Divider()
.padding(20)
#endif
if !model.addableItems().isEmpty {
Section(header: Text("Available")) {
ForEach(model.addableItems()) { item in
HStack {
Text(label(item))
Spacer()
Button {
model.add(item)
} label: {
Label("Add to Favorites", systemImage: "heart")
#if os(tvOS)
.font(.system(size: 30))
#endif
}
#if !os(tvOS)
.buttonStyle(.borderless)
#endif
}
}
}
#if os(tvOS)
.padding(.trailing, 40)
#endif
}
}
.labelStyle(.iconOnly)
}
func label(_ item: FavoriteItem) -> String {
switch item.section {
case let .playlist(_, id):
return playlistsModel.find(id: id)?.title ?? "Playlist".localized()
default:
return item.section.label.localized()
}
}
}
struct EditFavorites_Previews: PreviewProvider {
static var previews: some View {
EditFavorites()
.injectFixtureEnvironmentObjects()
}
}

View File

@@ -0,0 +1,302 @@
import Defaults
import SwiftUI
struct HomeSettings: View {
private var model = FavoritesModel.shared
@Default(.favorites) private var favorites
@Default(.showHome) private var showHome
@Default(.showFavoritesInHome) private var showFavoritesInHome
@Default(.showQueueInHome) private var showQueueInHome
@Default(.showOpenActionsInHome) private var showOpenActionsInHome
@Default(.showOpenActionsToolbarItem) private var showOpenActionsToolbarItem
@ObservedObject private var accounts = AccountsModel.shared
var body: some View {
Group {
#if os(tvOS)
ScrollView {
LazyVStack {
homeSettings
.padding(.horizontal)
editor
}
}
.frame(width: 1000)
#else
List {
homeSettings
editor
}
#endif
}
.navigationTitle("Home Settings")
}
var editor: some View {
Group {
Section(header: SettingsHeader(text: "Favorites")) {
if favorites.isEmpty {
Text("Favorites is empty")
.padding(.vertical)
.foregroundColor(.secondary)
}
ForEach(favorites) { item in
FavoriteItemEditor(item: item)
}
}
#if os(tvOS)
.padding(.trailing, 40)
#endif
if !model.addableItems().isEmpty {
Section(header: SettingsHeader(text: "Available")) {
ForEach(model.addableItems()) { item in
HStack {
FavoriteItemLabel(item: item)
Spacer()
Button {
model.add(item)
} label: {
Label("Add to Favorites", systemImage: "heart")
#if os(tvOS)
.font(.system(size: 30))
#endif
}
#if !os(tvOS)
.buttonStyle(.borderless)
#endif
}
}
}
#if os(tvOS)
.padding(.trailing, 40)
#endif
}
}
.labelStyle(.iconOnly)
}
private var homeSettings: some View {
Section(header: SettingsHeader(text: "Home".localized())) {
#if !os(tvOS)
if !accounts.isEmpty {
Toggle("Show Home", isOn: $showHome)
}
#endif
Toggle("Show Open Videos quick actions", isOn: $showOpenActionsInHome)
Toggle("Show Next in Queue", isOn: $showQueueInHome)
if !accounts.isEmpty {
Toggle("Show Favorites", isOn: $showFavoritesInHome)
}
}
}
}
struct FavoriteItemLabel: View {
var item: FavoriteItem
var body: some View {
Text(label)
.fontWeight(.bold)
}
var label: String {
switch item.section {
case let .playlist(_, id):
return PlaylistsModel.shared.find(id: id)?.title ?? "Playlist".localized()
default:
return item.section.label.localized()
}
}
}
struct FavoriteItemEditor: View {
var item: FavoriteItem
private var model: FavoritesModel { .shared }
@State private var listingStyle = WidgetListingStyle.horizontalCells
@State private var limit = 3
@State private var presentingRemoveAlert = false
var body: some View {
VStack(alignment: .leading) {
HStack {
FavoriteItemLabel(item: item)
Spacer()
HStack(spacing: 10) {
FavoriteItemEditorButton {
Label("Move Up", systemImage: "arrow.up")
} onTapGesture: {
model.moveUp(item)
}
FavoriteItemEditorButton {
Label("Move Down", systemImage: "arrow.down")
} onTapGesture: {
model.moveDown(item)
}
FavoriteItemEditorButton(color: .init("AppRedColor")) {
Label("Remove", systemImage: "trash")
} onTapGesture: {
presentingRemoveAlert = true
}
.alert(isPresented: $presentingRemoveAlert) {
Alert(
title: Text(
String(
format: "Are you sure you want to remove %@ from Favorites?".localized(),
item.section.label.localized()
)
),
message: Text("This cannot be reverted"),
primaryButton: .destructive(Text("Remove")) {
model.remove(item)
},
secondaryButton: .cancel()
)
}
}
}
listingStylePicker
.padding(.vertical, 5)
limitInput
#if !os(iOS)
Divider()
#endif
}
.onAppear(perform: setupEditor)
#if !os(tvOS)
.buttonStyle(.borderless)
#endif
}
var listingStylePicker: some View {
Picker("Listing Style", selection: $listingStyle) {
Text("Cells").tag(WidgetListingStyle.horizontalCells)
Text("List").tag(WidgetListingStyle.list)
}
.onChange(of: listingStyle) { newValue in
model.setListingStyle(newValue, item)
limit = min(limit, WidgetSettings.maxLimit(newValue))
}
.labelsHidden()
.pickerStyle(.segmented)
}
var limitInput: some View {
HStack {
Text("Limit")
Spacer()
#if !os(tvOS)
limitMinusButton
.disabled(limit == 1)
#endif
#if os(tvOS)
let textFieldWidth = 100.00
#else
let textFieldWidth = 30.00
#endif
TextField("Limit", value: $limit, formatter: NumberFormatter())
#if !os(macOS)
.keyboardType(.numberPad)
#endif
.labelsHidden()
.frame(width: textFieldWidth, alignment: .trailing)
.multilineTextAlignment(.center)
.onChange(of: limit) { newValue in
let value = min(limit, WidgetSettings.maxLimit(listingStyle))
if newValue <= 0 || newValue != value {
limit = value
} else {
model.setLimit(value, item)
}
}
#if !os(tvOS)
limitPlusButton
.disabled(limit == WidgetSettings.maxLimit(listingStyle))
#endif
}
}
#if !os(tvOS)
var limitMinusButton: some View {
FavoriteItemEditorButton {
Label("Minus", systemImage: "minus")
} onTapGesture: {
limit = max(1, limit - 1)
}
}
var limitPlusButton: some View {
FavoriteItemEditorButton {
Label("Plus", systemImage: "plus")
} onTapGesture: {
limit = max(1, limit + 1)
}
}
#endif
func setupEditor() {
listingStyle = model.listingStyle(item)
limit = model.limit(item)
}
}
struct FavoriteItemEditorButton<LabelView: View>: View {
var color = Color.accentColor
var label: LabelView
var onTapGesture: () -> Void = {}
init(
color: Color = .accentColor,
@ViewBuilder label: () -> LabelView,
onTapGesture: @escaping () -> Void = {}
) {
self.color = color
self.label = label()
self.onTapGesture = onTapGesture
}
var body: some View {
#if os(tvOS)
Button(action: onTapGesture) {
label
}
#else
label
.imageScale(.medium)
.labelStyle(.iconOnly)
.padding(7)
.frame(minWidth: 40, minHeight: 40)
.foregroundColor(color)
.accessibilityAddTraits(.isButton)
#if os(iOS)
.background(RoundedRectangle(cornerRadius: 4).strokeBorder(lineWidth: 1).foregroundColor(color))
#endif
.contentShape(Rectangle())
.onTapGesture(perform: onTapGesture)
#endif
}
}
struct HomeSettings_Previews: PreviewProvider {
static var previews: some View {
HomeSettings()
.injectFixtureEnvironmentObjects()
}
}