Home settings

This commit is contained in:
Arkadiusz Fal 2022-11-11 21:28:40 +01:00
parent ef1f95a3ad
commit 51bd46b3ae
11 changed files with 202 additions and 139 deletions

View File

@ -4,11 +4,11 @@ import Foundation
struct FavoritesModel { struct FavoritesModel {
static let shared = FavoritesModel() static let shared = FavoritesModel()
@Default(.showFavoritesInHome) var showFavoritesInHome
@Default(.favorites) var all @Default(.favorites) var all
@Default(.visibleSections) var visibleSections
var isEnabled: Bool { var isEnabled: Bool {
visibleSections.contains(.home) showFavoritesInHome
} }
func contains(_ item: FavoriteItem) -> Bool { func contains(_ item: FavoriteItem) -> Bool {

View File

@ -21,7 +21,11 @@ extension Defaults.Keys {
static let enableReturnYouTubeDislike = Key<Bool>("enableReturnYouTubeDislike", default: false) static let enableReturnYouTubeDislike = Key<Bool>("enableReturnYouTubeDislike", default: false)
static let homeHistoryItems = Key<Int>("homeHistoryItems", default: 30) static let showHome = Key<Bool>("showHome", default: true)
static let showOpenActionsInHome = Key<Bool>("showOpenActionsInHome", default: true)
static let showOpenActionsToolbarItem = Key<Bool>("showOpenActionsToolbarItem", default: false)
static let showFavoritesInHome = Key<Bool>("showFavoritesInHome", default: true)
static let homeHistoryItems = Key<Int>("homeHistoryItems", default: 10)
static let favorites = Key<[FavoriteItem]>("favorites", default: []) static let favorites = Key<[FavoriteItem]>("favorites", default: [])
#if !os(tvOS) #if !os(tvOS)
@ -169,7 +173,7 @@ extension Defaults.Keys {
static let trendingCategory = Key<TrendingCategory>("trendingCategory", default: .default) static let trendingCategory = Key<TrendingCategory>("trendingCategory", default: .default)
static let trendingCountry = Key<Country>("trendingCountry", default: .us) static let trendingCountry = Key<Country>("trendingCountry", default: .us)
static let visibleSections = Key<Set<VisibleSection>>("visibleSections", default: [.home]) static let visibleSections = Key<Set<VisibleSection>>("visibleSections", default: [.subscriptions, .trending, .playlists])
#if os(iOS) #if os(iOS)
static let enterFullscreenInLandscape = Key<Bool>("enterFullscreenInLandscape", default: UIDevice.current.userInterfaceIdiom == .phone) static let enterFullscreenInLandscape = Key<Bool>("enterFullscreenInLandscape", default: UIDevice.current.userInterfaceIdiom == .phone)
@ -234,7 +238,7 @@ enum PlayerSidebarSetting: String, CaseIterable, Defaults.Serializable {
} }
enum VisibleSection: String, CaseIterable, Comparable, Defaults.Serializable { enum VisibleSection: String, CaseIterable, Comparable, Defaults.Serializable {
case home, subscriptions, popular, trending, playlists case subscriptions, popular, trending, playlists
var title: String { var title: String {
rawValue.capitalized.localized() rawValue.capitalized.localized()
@ -242,8 +246,6 @@ enum VisibleSection: String, CaseIterable, Comparable, Defaults.Serializable {
var tabSelection: TabSelection { var tabSelection: TabSelection {
switch self { switch self {
case .home:
return TabSelection.home
case .subscriptions: case .subscriptions:
return TabSelection.subscriptions return TabSelection.subscriptions
case .popular: case .popular:
@ -257,16 +259,14 @@ enum VisibleSection: String, CaseIterable, Comparable, Defaults.Serializable {
private var sortOrder: Int { private var sortOrder: Int {
switch self { switch self {
case .home:
return 0
case .subscriptions: case .subscriptions:
return 1 return 0
case .popular: case .popular:
return 2 return 1
case .trending: case .trending:
return 3 return 2
case .playlists: case .playlists:
return 4 return 3
} }
} }

View File

@ -18,43 +18,47 @@ struct HomeView: View {
@Default(.favorites) private var favorites @Default(.favorites) private var favorites
#endif #endif
@Default(.homeHistoryItems) private var homeHistoryItems @Default(.homeHistoryItems) private var homeHistoryItems
@Default(.showFavoritesInHome) private var showFavoritesInHome
@Default(.showOpenActionsInHome) private var showOpenActionsInHome
private var navigation: NavigationModel { .shared } private var navigation: NavigationModel { .shared }
var body: some View { var body: some View {
BrowserPlayerControls { BrowserPlayerControls {
ScrollView(.vertical, showsIndicators: false) { ScrollView(.vertical, showsIndicators: false) {
HStack { if showOpenActionsInHome {
#if os(tvOS) HStack {
OpenVideosButton(text: "Open Video", imageSystemName: "globe") { #if os(tvOS)
NavigationModel.shared.presentingOpenVideos = true OpenVideosButton(text: "Open Video", imageSystemName: "globe") {
} NavigationModel.shared.presentingOpenVideos = true
.frame(maxWidth: 600) }
.frame(maxWidth: 600)
#else
OpenVideosButton(text: "Files", imageSystemName: "folder") {
NavigationModel.shared.presentingFileImporter = true
}
OpenVideosButton(text: "Paste", imageSystemName: "doc.on.clipboard.fill") {
OpenVideosModel.shared.openURLsFromClipboard(playbackMode: .playNow)
}
OpenVideosButton(imageSystemName: "ellipsis") {
NavigationModel.shared.presentingOpenVideos = true
}
.frame(maxWidth: 40)
#endif
}
#if os(iOS)
.padding(.top, RefreshControl.navigationBarTitleDisplayMode == .inline ? 15 : 0)
#else #else
OpenVideosButton(text: "Files", imageSystemName: "folder") { .padding(.top, 15)
NavigationModel.shared.presentingFileImporter = true #endif
} #if os(tvOS)
OpenVideosButton(text: "Paste", imageSystemName: "doc.on.clipboard.fill") { .padding(.horizontal, 40)
OpenVideosModel.shared.openURLsFromClipboard(playbackMode: .playNow) #else
} .padding(.horizontal, 15)
OpenVideosButton(imageSystemName: "ellipsis") {
NavigationModel.shared.presentingOpenVideos = true
}
.frame(maxWidth: 40)
#endif #endif
} }
#if os(iOS)
.padding(.top, RefreshControl.navigationBarTitleDisplayMode == .inline ? 15 : 0)
#else
.padding(.top, 15)
#endif
#if os(tvOS)
.padding(.horizontal, 40)
#else
.padding(.horizontal, 15)
#endif
if !accounts.current.isNil { if !accounts.current.isNil, showFavoritesInHome {
#if os(tvOS) #if os(tvOS)
ForEach(Defaults[.favorites]) { item in ForEach(Defaults[.favorites]) { item in
FavoriteItemView(item: item, dragging: $dragging) FavoriteItemView(item: item, dragging: $dragging)
@ -75,19 +79,21 @@ struct HomeView: View {
#endif #endif
} }
VStack { if homeHistoryItems > 0 {
Text("History") VStack {
Text("History")
#if os(tvOS) #if os(tvOS)
.padding(.horizontal, 40) .padding(.horizontal, 40)
#else #else
.padding(.horizontal, 15) .padding(.horizontal, 15)
#endif #endif
.font(.title3.bold()) .font(.title3.bold())
.frame(maxWidth: .infinity, alignment: .leading) .frame(maxWidth: .infinity, alignment: .leading)
.foregroundColor(.secondary) .foregroundColor(.secondary)
HistoryView(limit: homeHistoryItems) HistoryView(limit: homeHistoryItems)
}
} }
#if !os(tvOS) #if !os(tvOS)

View File

@ -5,6 +5,8 @@ import SwiftUI
#endif #endif
struct AppSidebarNavigation: View { struct AppSidebarNavigation: View {
@Default(.showOpenActionsToolbarItem) private var showOpenActionsToolbarItem
@EnvironmentObject<AccountsModel> private var accounts @EnvironmentObject<AccountsModel> private var accounts
@EnvironmentObject<NavigationModel> private var navigation @EnvironmentObject<NavigationModel> private var navigation
@ -75,10 +77,12 @@ struct AppSidebarNavigation: View {
#endif #endif
ToolbarItemGroup(placement: openVideosToolbarItemPlacement) { ToolbarItemGroup(placement: openVideosToolbarItemPlacement) {
Button { if showOpenActionsToolbarItem {
navigation.presentingOpenVideos = true Button {
} label: { navigation.presentingOpenVideos = true
Label("Open Videos", systemImage: "play.circle.fill") } label: {
Label("Open Videos", systemImage: "play.circle.fill")
}
} }
} }

View File

@ -13,36 +13,48 @@ struct AppTabNavigation: View {
@EnvironmentObject<SubscriptionsModel> private var subscriptions @EnvironmentObject<SubscriptionsModel> private var subscriptions
@EnvironmentObject<ThumbnailsModel> private var thumbnailsModel @EnvironmentObject<ThumbnailsModel> private var thumbnailsModel
@Default(.showHome) private var showHome
@Default(.showOpenActionsToolbarItem) private var showOpenActionsToolbarItem
@Default(.visibleSections) private var visibleSections @Default(.visibleSections) private var visibleSections
let persistenceController = PersistenceController.shared let persistenceController = PersistenceController.shared
var body: some View { var body: some View {
TabView(selection: navigation.tabSelectionBinding) { TabView(selection: navigation.tabSelectionBinding) {
if visibleSections.contains(.home) { let tabs = Group {
homeNavigationView if showHome {
homeNavigationView
}
if !accounts.isEmpty {
if subscriptionsVisible {
subscriptionsNavigationView
}
if visibleSections.contains(.popular), accounts.app.supportsPopular, visibleSections.count < 5 {
popularNavigationView
}
if visibleSections.contains(.trending) {
trendingNavigationView
}
if playlistsVisible {
playlistsNavigationView
}
searchNavigationView
}
} }
if subscriptionsVisible { if #available(iOS 16, tvOS 16, *) {
subscriptionsNavigationView tabs
} .toolbar(accounts.isEmpty ? .hidden : .visible, for: .tabBar)
} else {
if visibleSections.contains(.popular), accounts.app.supportsPopular, visibleSections.count < 5 { tabs
popularNavigationView
}
if visibleSections.contains(.trending) {
trendingNavigationView
}
if playlistsVisible {
playlistsNavigationView
}
if !accounts.isEmpty {
searchNavigationView
} }
} }
.id(accounts.current?.id ?? "") .id(accounts.current?.id ?? "")
.overlay(playlistView) .overlay(playlistView)
.overlay(channelView) .overlay(channelView)
@ -141,8 +153,10 @@ struct AppTabNavigation: View {
} }
ToolbarItemGroup(placement: .navigationBarTrailing) { ToolbarItemGroup(placement: .navigationBarTrailing) {
Button(action: { navigation.presentingOpenVideos = true }) { if showOpenActionsToolbarItem {
Label("Open Videos", systemImage: "play.circle.fill") Button(action: { navigation.presentingOpenVideos = true }) {
Label("Open Videos", systemImage: "play.circle.fill")
}
} }
AccountsMenuView() AccountsMenuView()
} }

View File

@ -5,6 +5,7 @@ struct Sidebar: View {
@EnvironmentObject<AccountsModel> private var accounts @EnvironmentObject<AccountsModel> private var accounts
@EnvironmentObject<NavigationModel> private var navigation @EnvironmentObject<NavigationModel> private var navigation
@Default(.showHome) private var showHome
@Default(.visibleSections) private var visibleSections @Default(.visibleSections) private var visibleSections
var body: some View { var body: some View {
@ -40,40 +41,40 @@ struct Sidebar: View {
var mainNavigationLinks: some View { var mainNavigationLinks: some View {
Section(header: Text("Videos")) { Section(header: Text("Videos")) {
if visibleSections.contains(.home) { if showHome {
NavigationLink(destination: LazyView(HomeView()), tag: TabSelection.home, selection: $navigation.tabSelection) { NavigationLink(destination: LazyView(HomeView()), tag: TabSelection.home, selection: $navigation.tabSelection) {
Label("Home", systemImage: "house") Label("Home", systemImage: "house")
.accessibility(label: Text("Home")) .accessibility(label: Text("Home"))
} }
.id("favorites") .id("favorites")
} }
if visibleSections.contains(.subscriptions),
accounts.app.supportsSubscriptions && accounts.signedIn
{
NavigationLink(destination: LazyView(SubscriptionsView()), tag: TabSelection.subscriptions, selection: $navigation.tabSelection) {
Label("Subscriptions", systemImage: "star.circle")
.accessibility(label: Text("Subscriptions"))
}
.id("subscriptions")
}
if visibleSections.contains(.popular), accounts.app.supportsPopular {
NavigationLink(destination: LazyView(PopularView()), tag: TabSelection.popular, selection: $navigation.tabSelection) {
Label("Popular", systemImage: "arrow.up.right.circle")
.accessibility(label: Text("Popular"))
}
.id("popular")
}
if visibleSections.contains(.trending) {
NavigationLink(destination: LazyView(TrendingView()), tag: TabSelection.trending, selection: $navigation.tabSelection) {
Label("Trending", systemImage: "chart.bar")
.accessibility(label: Text("Trending"))
}
.id("trending")
}
if !accounts.isEmpty { if !accounts.isEmpty {
if visibleSections.contains(.subscriptions),
accounts.app.supportsSubscriptions && accounts.signedIn
{
NavigationLink(destination: LazyView(SubscriptionsView()), tag: TabSelection.subscriptions, selection: $navigation.tabSelection) {
Label("Subscriptions", systemImage: "star.circle")
.accessibility(label: Text("Subscriptions"))
}
.id("subscriptions")
}
if visibleSections.contains(.popular), accounts.app.supportsPopular {
NavigationLink(destination: LazyView(PopularView()), tag: TabSelection.popular, selection: $navigation.tabSelection) {
Label("Popular", systemImage: "arrow.up.right.circle")
.accessibility(label: Text("Popular"))
}
.id("popular")
}
if visibleSections.contains(.trending) {
NavigationLink(destination: LazyView(TrendingView()), tag: TabSelection.trending, selection: $navigation.tabSelection) {
Label("Trending", systemImage: "chart.bar")
.accessibility(label: Text("Trending"))
}
.id("trending")
}
NavigationLink(destination: LazyView(SearchView()), tag: TabSelection.search, selection: $navigation.tabSelection) { NavigationLink(destination: LazyView(SearchView()), tag: TabSelection.search, selection: $navigation.tabSelection) {
Label("Search", systemImage: "magnifyingglass") Label("Search", systemImage: "magnifyingglass")
.accessibility(label: Text("Search")) .accessibility(label: Text("Search"))

View File

@ -29,6 +29,7 @@ struct SearchView: View {
@Default(.recentlyOpened) private var recentlyOpened @Default(.recentlyOpened) private var recentlyOpened
@Default(.saveRecents) private var saveRecents @Default(.saveRecents) private var saveRecents
@Default(.showHome) private var showHome
private var videos = [Video]() private var videos = [Video]()
@ -209,13 +210,11 @@ struct SearchView: View {
visibleSections.append(.playlists) visibleSections.append(.playlists)
} }
[VisibleSection.home, .trending].forEach { section in if preferred.contains(.trending) {
if preferred.contains(section) { visibleSections.append(.trending)
visibleSections.append(section)
}
} }
return !visibleSections.isEmpty return !visibleSections.isEmpty || showHome
} }
private var results: some View { private var results: some View {

View File

@ -13,12 +13,24 @@ struct BrowsingSettings: View {
@Default(.thumbnailsQuality) private var thumbnailsQuality @Default(.thumbnailsQuality) private var thumbnailsQuality
@Default(.channelOnThumbnail) private var channelOnThumbnail @Default(.channelOnThumbnail) private var channelOnThumbnail
@Default(.timeOnThumbnail) private var timeOnThumbnail @Default(.timeOnThumbnail) private var timeOnThumbnail
@Default(.showHome) private var showHome
@Default(.showFavoritesInHome) private var showFavoritesInHome
@Default(.showOpenActionsInHome) private var showOpenActionsInHome
@Default(.showOpenActionsToolbarItem) private var showOpenActionsToolbarItem
@Default(.homeHistoryItems) private var homeHistoryItems
@Default(.visibleSections) private var visibleSections @Default(.visibleSections) private var visibleSections
@EnvironmentObject<AccountsModel> private var accounts
@State private var homeHistoryItemsText = ""
var body: some View { var body: some View {
Group { Group {
#if os(macOS) #if os(macOS)
sections VStack(alignment: .leading) {
sections
Spacer()
}
#else #else
List { List {
sections sections
@ -38,14 +50,45 @@ struct BrowsingSettings: View {
private var sections: some View { private var sections: some View {
Group { Group {
homeSettings
interfaceSettings interfaceSettings
thumbnailsSettings if !accounts.isEmpty {
visibleSectionsSettings thumbnailsSettings
visibleSectionsSettings
}
}
}
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)
if !accounts.isEmpty {
Toggle("Show Favorites", isOn: $showFavoritesInHome)
}
HStack {
TextField("Recent history items", text: $homeHistoryItemsText)
#if !os(macOS)
.keyboardType(.URL)
#endif
.onAppear {
homeHistoryItemsText = String(homeHistoryItems)
}
.onChange(of: homeHistoryItemsText) { newValue in
homeHistoryItems = Int(newValue) ?? 10
}
}
.multilineTextAlignment(.trailing)
} }
} }
private var interfaceSettings: some View { private var interfaceSettings: some View {
Section(header: SettingsHeader(text: "Interface".localized())) { Section(header: SettingsHeader(text: "Interface".localized())) {
Toggle("Show Open Videos toolbar button", isOn: $showOpenActionsToolbarItem)
#if os(iOS) #if os(iOS)
Toggle("Lock portrait mode", isOn: $lockPortraitWhenBrowsing) Toggle("Lock portrait mode", isOn: $lockPortraitWhenBrowsing)
.onChange(of: lockPortraitWhenBrowsing) { lock in .onChange(of: lockPortraitWhenBrowsing) { lock in
@ -57,11 +100,13 @@ struct BrowsingSettings: View {
} }
#endif #endif
#if !os(tvOS) if !accounts.isEmpty {
Toggle("Show account username", isOn: $accountPickerDisplaysUsername) #if !os(tvOS)
#endif Toggle("Show account username", isOn: $accountPickerDisplaysUsername)
#endif
Toggle("Show anonymous accounts", isOn: $accountPickerDisplaysAnonymousAccounts) Toggle("Show anonymous accounts", isOn: $accountPickerDisplaysAnonymousAccounts)
}
} }
} }

View File

@ -34,15 +34,13 @@ struct SettingsView: View {
var settings: some View { var settings: some View {
#if os(macOS) #if os(macOS)
TabView(selection: $selection) { TabView(selection: $selection) {
if !accounts.isEmpty { Form {
Form { BrowsingSettings()
BrowsingSettings()
}
.tabItem {
Label("Browsing", systemImage: "list.and.film")
}
.tag(Optional(Tabs.browsing))
} }
.tabItem {
Label("Browsing", systemImage: "list.and.film")
}
.tag(Optional(Tabs.browsing))
Form { Form {
PlayerSettings() PlayerSettings()
@ -125,12 +123,10 @@ struct SettingsView: View {
} }
#endif #endif
if !accounts.isEmpty { NavigationLink {
NavigationLink { BrowsingSettings()
BrowsingSettings() } label: {
} label: { Label("Browsing", systemImage: "list.and.film")
Label("Browsing", systemImage: "list.and.film")
}
} }
NavigationLink { NavigationLink {
@ -221,9 +217,9 @@ struct SettingsView: View {
private var windowHeight: Double { private var windowHeight: Double {
switch selection { switch selection {
case nil: case nil:
return accounts.isEmpty ? 680 : 400 return accounts.isEmpty ? 680 : 520
case .browsing: case .browsing:
return 400 return 520
case .player: case .player:
return 680 return 680
case .quality: case .quality:
@ -233,7 +229,7 @@ struct SettingsView: View {
case .sponsorBlock: case .sponsorBlock:
return 700 return 700
case .advanced: case .advanced:
return 650 return 750
case .help: case .help:
return 600 return 600
} }

View File

@ -203,7 +203,7 @@ struct YatteeApp: App {
recents.clear() recents.clear()
} }
var section = Defaults[.visibleSections].min()?.tabSelection var section = Defaults[.showHome] ? TabSelection.home : Defaults[.visibleSections].min()?.tabSelection
#if os(macOS) #if os(macOS)
if section == .playlists { if section == .playlists {

View File

@ -13,11 +13,9 @@ struct TVNavigationView: View {
var body: some View { var body: some View {
NavigationView { NavigationView {
TabView(selection: navigation.tabSelectionBinding) { TabView(selection: navigation.tabSelectionBinding) {
if visibleSections.contains(.home) { LazyView(HomeView())
LazyView(HomeView()) .tabItem { Text("Home") }
.tabItem { Text("Home") } .tag(TabSelection.home)
.tag(TabSelection.home)
}
if visibleSections.contains(.subscriptions), accounts.app.supportsSubscriptions, accounts.api.signedIn { if visibleSections.contains(.subscriptions), accounts.app.supportsSubscriptions, accounts.api.signedIn {
LazyView(SubscriptionsView()) LazyView(SubscriptionsView())