mirror of
https://github.com/yattee/yattee.git
synced 2024-12-22 21:43:41 +00:00
Add Welcome screen
This commit is contained in:
parent
0d1eaaca5c
commit
ec395ff2e0
@ -4,9 +4,11 @@ import SwiftUI
|
|||||||
struct FixtureEnvironmentObjectsModifier: ViewModifier {
|
struct FixtureEnvironmentObjectsModifier: ViewModifier {
|
||||||
func body(content: Content) -> some View {
|
func body(content: Content) -> some View {
|
||||||
content
|
content
|
||||||
|
.environmentObject(AccountsModel())
|
||||||
.environmentObject(InstancesModel())
|
.environmentObject(InstancesModel())
|
||||||
.environmentObject(api)
|
.environmentObject(invidious)
|
||||||
.environmentObject(NavigationModel())
|
.environmentObject(NavigationModel())
|
||||||
|
.environmentObject(PipedAPI())
|
||||||
.environmentObject(player)
|
.environmentObject(player)
|
||||||
.environmentObject(PlaylistsModel())
|
.environmentObject(PlaylistsModel())
|
||||||
.environmentObject(RecentsModel())
|
.environmentObject(RecentsModel())
|
||||||
@ -14,7 +16,7 @@ struct FixtureEnvironmentObjectsModifier: ViewModifier {
|
|||||||
.environmentObject(subscriptions)
|
.environmentObject(subscriptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var api: InvidiousAPI {
|
private var invidious: InvidiousAPI {
|
||||||
let api = InvidiousAPI()
|
let api = InvidiousAPI()
|
||||||
|
|
||||||
api.validInstance = true
|
api.validInstance = true
|
||||||
|
@ -14,8 +14,12 @@ final class AccountsModel: ObservableObject {
|
|||||||
Defaults[.instances].map(\.anonymousAccount) + Defaults[.accounts]
|
Defaults[.instances].map(\.anonymousAccount) + Defaults[.accounts]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isEmpty: Bool {
|
||||||
|
account.isNil
|
||||||
|
}
|
||||||
|
|
||||||
var signedIn: Bool {
|
var signedIn: Bool {
|
||||||
!account.isNil && !account.anonymous
|
!isEmpty && !account.anonymous
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
@ -28,13 +32,17 @@ final class AccountsModel: ObservableObject {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setAccount(_ account: Instance.Account) {
|
func setAccount(_ account: Instance.Account! = nil) {
|
||||||
guard account != self.account else {
|
guard account != self.account else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
self.account = account
|
self.account = account
|
||||||
|
|
||||||
|
guard !account.isNil else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
switch account.instance.app {
|
switch account.instance.app {
|
||||||
case .invidious:
|
case .invidious:
|
||||||
invidious.setAccount(account)
|
invidious.setAccount(account)
|
||||||
|
@ -30,6 +30,7 @@ final class NavigationModel: ObservableObject {
|
|||||||
@Published var sidebarSectionChanged = false
|
@Published var sidebarSectionChanged = false
|
||||||
|
|
||||||
@Published var presentingSettings = false
|
@Published var presentingSettings = false
|
||||||
|
@Published var presentingWelcomeScreen = false
|
||||||
|
|
||||||
var tabSelectionBinding: Binding<TabSelection> {
|
var tabSelectionBinding: Binding<TabSelection> {
|
||||||
Binding<TabSelection>(
|
Binding<TabSelection>(
|
||||||
|
@ -302,6 +302,12 @@
|
|||||||
37E64DD126D597EB00C71877 /* SubscriptionsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E64DD026D597EB00C71877 /* SubscriptionsModel.swift */; };
|
37E64DD126D597EB00C71877 /* SubscriptionsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E64DD026D597EB00C71877 /* SubscriptionsModel.swift */; };
|
||||||
37E64DD226D597EB00C71877 /* SubscriptionsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E64DD026D597EB00C71877 /* SubscriptionsModel.swift */; };
|
37E64DD226D597EB00C71877 /* SubscriptionsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E64DD026D597EB00C71877 /* SubscriptionsModel.swift */; };
|
||||||
37E64DD326D597EB00C71877 /* SubscriptionsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E64DD026D597EB00C71877 /* SubscriptionsModel.swift */; };
|
37E64DD326D597EB00C71877 /* SubscriptionsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E64DD026D597EB00C71877 /* SubscriptionsModel.swift */; };
|
||||||
|
37E70923271CD43000D34DDE /* WelcomeScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E70922271CD43000D34DDE /* WelcomeScreen.swift */; };
|
||||||
|
37E70924271CD43000D34DDE /* WelcomeScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E70922271CD43000D34DDE /* WelcomeScreen.swift */; };
|
||||||
|
37E70925271CD43000D34DDE /* WelcomeScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E70922271CD43000D34DDE /* WelcomeScreen.swift */; };
|
||||||
|
37E70927271CDDAE00D34DDE /* OpenSettingsButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E70926271CDDAE00D34DDE /* OpenSettingsButton.swift */; };
|
||||||
|
37E70928271CDDAE00D34DDE /* OpenSettingsButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E70926271CDDAE00D34DDE /* OpenSettingsButton.swift */; };
|
||||||
|
37E70929271CDDAE00D34DDE /* OpenSettingsButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E70926271CDDAE00D34DDE /* OpenSettingsButton.swift */; };
|
||||||
37EAD86B267B9C5600D9E01B /* SponsorBlockAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37EAD86A267B9C5600D9E01B /* SponsorBlockAPI.swift */; };
|
37EAD86B267B9C5600D9E01B /* SponsorBlockAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37EAD86A267B9C5600D9E01B /* SponsorBlockAPI.swift */; };
|
||||||
37EAD86C267B9C5600D9E01B /* SponsorBlockAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37EAD86A267B9C5600D9E01B /* SponsorBlockAPI.swift */; };
|
37EAD86C267B9C5600D9E01B /* SponsorBlockAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37EAD86A267B9C5600D9E01B /* SponsorBlockAPI.swift */; };
|
||||||
37EAD86D267B9C5600D9E01B /* SponsorBlockAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37EAD86A267B9C5600D9E01B /* SponsorBlockAPI.swift */; };
|
37EAD86D267B9C5600D9E01B /* SponsorBlockAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37EAD86A267B9C5600D9E01B /* SponsorBlockAPI.swift */; };
|
||||||
@ -467,6 +473,8 @@
|
|||||||
37DD87C6271C9CFE0027CBF9 /* PlayerStreams.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerStreams.swift; sourceTree = "<group>"; };
|
37DD87C6271C9CFE0027CBF9 /* PlayerStreams.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerStreams.swift; sourceTree = "<group>"; };
|
||||||
37E2EEAA270656EC00170416 /* PlayerControlsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerControlsView.swift; sourceTree = "<group>"; };
|
37E2EEAA270656EC00170416 /* PlayerControlsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerControlsView.swift; sourceTree = "<group>"; };
|
||||||
37E64DD026D597EB00C71877 /* SubscriptionsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionsModel.swift; sourceTree = "<group>"; };
|
37E64DD026D597EB00C71877 /* SubscriptionsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionsModel.swift; sourceTree = "<group>"; };
|
||||||
|
37E70922271CD43000D34DDE /* WelcomeScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeScreen.swift; sourceTree = "<group>"; };
|
||||||
|
37E70926271CDDAE00D34DDE /* OpenSettingsButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenSettingsButton.swift; sourceTree = "<group>"; };
|
||||||
37EAD86A267B9C5600D9E01B /* SponsorBlockAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SponsorBlockAPI.swift; sourceTree = "<group>"; };
|
37EAD86A267B9C5600D9E01B /* SponsorBlockAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SponsorBlockAPI.swift; sourceTree = "<group>"; };
|
||||||
37EAD86E267B9ED100D9E01B /* Segment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Segment.swift; sourceTree = "<group>"; };
|
37EAD86E267B9ED100D9E01B /* Segment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Segment.swift; sourceTree = "<group>"; };
|
||||||
37F49BA226CAA59B00304AC0 /* Playlist+Fixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Playlist+Fixtures.swift"; sourceTree = "<group>"; };
|
37F49BA226CAA59B00304AC0 /* Playlist+Fixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Playlist+Fixtures.swift"; sourceTree = "<group>"; };
|
||||||
@ -615,6 +623,7 @@
|
|||||||
children = (
|
children = (
|
||||||
37BA793E26DB8F97002A0235 /* ChannelVideosView.swift */,
|
37BA793E26DB8F97002A0235 /* ChannelVideosView.swift */,
|
||||||
37152EE926EFEB95004FB96D /* LazyView.swift */,
|
37152EE926EFEB95004FB96D /* LazyView.swift */,
|
||||||
|
37E70926271CDDAE00D34DDE /* OpenSettingsButton.swift */,
|
||||||
37E2EEAA270656EC00170416 /* PlayerControlsView.swift */,
|
37E2EEAA270656EC00170416 /* PlayerControlsView.swift */,
|
||||||
37BA793A26DB8EE4002A0235 /* PlaylistVideosView.swift */,
|
37BA793A26DB8EE4002A0235 /* PlaylistVideosView.swift */,
|
||||||
37AAF27D26737323007FC770 /* PopularView.swift */,
|
37AAF27D26737323007FC770 /* PopularView.swift */,
|
||||||
@ -622,6 +631,7 @@
|
|||||||
376B2E0626F920D600B1D64D /* SignInRequiredView.swift */,
|
376B2E0626F920D600B1D64D /* SignInRequiredView.swift */,
|
||||||
37AAF29F26741C97007FC770 /* SubscriptionsView.swift */,
|
37AAF29F26741C97007FC770 /* SubscriptionsView.swift */,
|
||||||
37B17D9F268A1F25006AEE9B /* VideoContextMenuView.swift */,
|
37B17D9F268A1F25006AEE9B /* VideoContextMenuView.swift */,
|
||||||
|
37E70922271CD43000D34DDE /* WelcomeScreen.swift */,
|
||||||
);
|
);
|
||||||
path = Views;
|
path = Views;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -1332,11 +1342,13 @@
|
|||||||
37732FF42703D32400F04329 /* Sidebar.swift in Sources */,
|
37732FF42703D32400F04329 /* Sidebar.swift in Sources */,
|
||||||
37D4B19726717E1500C925CA /* Video.swift in Sources */,
|
37D4B19726717E1500C925CA /* Video.swift in Sources */,
|
||||||
37484C2926FC83FF00287258 /* AccountFormView.swift in Sources */,
|
37484C2926FC83FF00287258 /* AccountFormView.swift in Sources */,
|
||||||
|
37E70927271CDDAE00D34DDE /* OpenSettingsButton.swift in Sources */,
|
||||||
371F2F1A269B43D300E4A7AB /* NavigationModel.swift in Sources */,
|
371F2F1A269B43D300E4A7AB /* NavigationModel.swift in Sources */,
|
||||||
37BE0BCF26A0E2D50092E2DB /* VideoPlayerView.swift in Sources */,
|
37BE0BCF26A0E2D50092E2DB /* VideoPlayerView.swift in Sources */,
|
||||||
37001563271B1F250049C794 /* AccountsModel.swift in Sources */,
|
37001563271B1F250049C794 /* AccountsModel.swift in Sources */,
|
||||||
37CC3F50270D010D00608308 /* VideoBanner.swift in Sources */,
|
37CC3F50270D010D00608308 /* VideoBanner.swift in Sources */,
|
||||||
378E50FB26FE8B9F00F49626 /* Instance.swift in Sources */,
|
378E50FB26FE8B9F00F49626 /* Instance.swift in Sources */,
|
||||||
|
37E70923271CD43000D34DDE /* WelcomeScreen.swift in Sources */,
|
||||||
37484C1D26FC83A400287258 /* InstancesSettingsView.swift in Sources */,
|
37484C1D26FC83A400287258 /* InstancesSettingsView.swift in Sources */,
|
||||||
37BD07BB2698AB60003EBB87 /* AppSidebarNavigation.swift in Sources */,
|
37BD07BB2698AB60003EBB87 /* AppSidebarNavigation.swift in Sources */,
|
||||||
37D4B0E42671614900C925CA /* PearvidiousApp.swift in Sources */,
|
37D4B0E42671614900C925CA /* PearvidiousApp.swift in Sources */,
|
||||||
@ -1355,6 +1367,7 @@
|
|||||||
3788AC2C26F6842D00F6BAA9 /* WatchNowSectionBody.swift in Sources */,
|
3788AC2C26F6842D00F6BAA9 /* WatchNowSectionBody.swift in Sources */,
|
||||||
37CEE4BE2677B670005A1EFE /* SingleAssetStream.swift in Sources */,
|
37CEE4BE2677B670005A1EFE /* SingleAssetStream.swift in Sources */,
|
||||||
37BA794826DC2E56002A0235 /* AppSidebarSubscriptions.swift in Sources */,
|
37BA794826DC2E56002A0235 /* AppSidebarSubscriptions.swift in Sources */,
|
||||||
|
37E70928271CDDAE00D34DDE /* OpenSettingsButton.swift in Sources */,
|
||||||
37EAD86C267B9C5600D9E01B /* SponsorBlockAPI.swift in Sources */,
|
37EAD86C267B9C5600D9E01B /* SponsorBlockAPI.swift in Sources */,
|
||||||
37CEE4C22677B697005A1EFE /* Stream.swift in Sources */,
|
37CEE4C22677B697005A1EFE /* Stream.swift in Sources */,
|
||||||
371F2F1B269B43D300E4A7AB /* NavigationModel.swift in Sources */,
|
371F2F1B269B43D300E4A7AB /* NavigationModel.swift in Sources */,
|
||||||
@ -1387,6 +1400,7 @@
|
|||||||
37B044B826F7AB9000E1419D /* SettingsView.swift in Sources */,
|
37B044B826F7AB9000E1419D /* SettingsView.swift in Sources */,
|
||||||
3765788A2685471400D4EA09 /* Playlist.swift in Sources */,
|
3765788A2685471400D4EA09 /* Playlist.swift in Sources */,
|
||||||
37E2EEAC270656EC00170416 /* PlayerControlsView.swift in Sources */,
|
37E2EEAC270656EC00170416 /* PlayerControlsView.swift in Sources */,
|
||||||
|
37E70924271CD43000D34DDE /* WelcomeScreen.swift in Sources */,
|
||||||
373CFACC26966264003CB2C6 /* SearchQuery.swift in Sources */,
|
373CFACC26966264003CB2C6 /* SearchQuery.swift in Sources */,
|
||||||
37AAF29126740715007FC770 /* Channel.swift in Sources */,
|
37AAF29126740715007FC770 /* Channel.swift in Sources */,
|
||||||
37BD07BC2698AB60003EBB87 /* AppSidebarNavigation.swift in Sources */,
|
37BD07BC2698AB60003EBB87 /* AppSidebarNavigation.swift in Sources */,
|
||||||
@ -1485,6 +1499,7 @@
|
|||||||
37141671267A8ACC006CA35D /* TrendingView.swift in Sources */,
|
37141671267A8ACC006CA35D /* TrendingView.swift in Sources */,
|
||||||
3788AC2926F6840700F6BAA9 /* WatchNowSection.swift in Sources */,
|
3788AC2926F6840700F6BAA9 /* WatchNowSection.swift in Sources */,
|
||||||
37319F0727103F94004ECCD0 /* PlayerQueue.swift in Sources */,
|
37319F0727103F94004ECCD0 /* PlayerQueue.swift in Sources */,
|
||||||
|
37E70925271CD43000D34DDE /* WelcomeScreen.swift in Sources */,
|
||||||
37DD87C9271C9CFE0027CBF9 /* PlayerStreams.swift in Sources */,
|
37DD87C9271C9CFE0027CBF9 /* PlayerStreams.swift in Sources */,
|
||||||
375168D82700FDB9008F96A6 /* Debounce.swift in Sources */,
|
375168D82700FDB9008F96A6 /* Debounce.swift in Sources */,
|
||||||
37BA794126DB8F97002A0235 /* ChannelVideosView.swift in Sources */,
|
37BA794126DB8F97002A0235 /* ChannelVideosView.swift in Sources */,
|
||||||
@ -1506,6 +1521,7 @@
|
|||||||
3743CA50270EFE3400E4D32B /* PlayerQueueRow.swift in Sources */,
|
3743CA50270EFE3400E4D32B /* PlayerQueueRow.swift in Sources */,
|
||||||
37A9966026D6F9B9006E3224 /* WatchNowView.swift in Sources */,
|
37A9966026D6F9B9006E3224 /* WatchNowView.swift in Sources */,
|
||||||
37001565271B1F250049C794 /* AccountsModel.swift in Sources */,
|
37001565271B1F250049C794 /* AccountsModel.swift in Sources */,
|
||||||
|
37E70929271CDDAE00D34DDE /* OpenSettingsButton.swift in Sources */,
|
||||||
37484C1F26FC83A400287258 /* InstancesSettingsView.swift in Sources */,
|
37484C1F26FC83A400287258 /* InstancesSettingsView.swift in Sources */,
|
||||||
37C7A1D7267BFD9D0010EAD6 /* SponsorBlockSegment.swift in Sources */,
|
37C7A1D7267BFD9D0010EAD6 /* SponsorBlockSegment.swift in Sources */,
|
||||||
376578932685490700D4EA09 /* PlaylistsView.swift in Sources */,
|
376578932685490700D4EA09 /* PlaylistsView.swift in Sources */,
|
||||||
|
@ -3,7 +3,6 @@ import SwiftUI
|
|||||||
|
|
||||||
struct AccountsMenuView: View {
|
struct AccountsMenuView: View {
|
||||||
@EnvironmentObject<AccountsModel> private var model
|
@EnvironmentObject<AccountsModel> private var model
|
||||||
@EnvironmentObject<InstancesModel> private var instancesModel
|
|
||||||
|
|
||||||
@Default(.instances) private var instances
|
@Default(.instances) private var instances
|
||||||
|
|
||||||
|
@ -37,7 +37,12 @@ struct AppSidebarNavigation: View {
|
|||||||
.toolbar { toolbarContent }
|
.toolbar { toolbarContent }
|
||||||
.frame(minWidth: sidebarMinWidth)
|
.frame(minWidth: sidebarMinWidth)
|
||||||
|
|
||||||
Text("Select section")
|
VStack {
|
||||||
|
Image(systemName: "play.tv")
|
||||||
|
.renderingMode(.original)
|
||||||
|
.font(.system(size: 60))
|
||||||
|
.foregroundColor(.accentColor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.environment(\.navigationStyle, .sidebar)
|
.environment(\.navigationStyle, .sidebar)
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,11 @@ struct ContentView: View {
|
|||||||
.environmentObject(recents)
|
.environmentObject(recents)
|
||||||
.environmentObject(search)
|
.environmentObject(search)
|
||||||
.environmentObject(subscriptions)
|
.environmentObject(subscriptions)
|
||||||
|
.sheet(isPresented: $navigation.presentingWelcomeScreen) {
|
||||||
|
WelcomeScreen()
|
||||||
|
.environmentObject(accounts)
|
||||||
|
.environmentObject(navigation)
|
||||||
|
}
|
||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
.fullScreenCover(isPresented: $player.presentingPlayer) {
|
.fullScreenCover(isPresented: $player.presentingPlayer) {
|
||||||
VideoPlayerView()
|
VideoPlayerView()
|
||||||
@ -68,8 +73,9 @@ struct ContentView: View {
|
|||||||
PlaylistFormView(playlist: $navigation.editedPlaylist)
|
PlaylistFormView(playlist: $navigation.editedPlaylist)
|
||||||
.environmentObject(playlists)
|
.environmentObject(playlists)
|
||||||
}
|
}
|
||||||
.sheet(isPresented: $navigation.presentingSettings) {
|
.sheet(isPresented: $navigation.presentingSettings, onDismiss: openWelcomeScreenIfAccountEmpty) {
|
||||||
SettingsView()
|
SettingsView()
|
||||||
|
.environmentObject(accounts)
|
||||||
.environmentObject(instances)
|
.environmentObject(instances)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -78,17 +84,29 @@ struct ContentView: View {
|
|||||||
func configure() {
|
func configure() {
|
||||||
SiestaLog.Category.enabled = .common
|
SiestaLog.Category.enabled = .common
|
||||||
|
|
||||||
if let account = instances.defaultAccount ??
|
|
||||||
// TODO: Remove when piped supports videos information
|
// TODO: Remove when piped supports videos information
|
||||||
|
if let account = instances.defaultAccount ??
|
||||||
accounts.all.first(where: { $0.instance.app == .invidious })
|
accounts.all.first(where: { $0.instance.app == .invidious })
|
||||||
{
|
{
|
||||||
accounts.setAccount(account)
|
accounts.setAccount(account)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if accounts.account.isNil {
|
||||||
|
navigation.presentingWelcomeScreen = true
|
||||||
|
}
|
||||||
player.accounts = accounts
|
player.accounts = accounts
|
||||||
playlists.accounts = accounts
|
playlists.accounts = accounts
|
||||||
search.accounts = accounts
|
search.accounts = accounts
|
||||||
subscriptions.accounts = accounts
|
subscriptions.accounts = accounts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func openWelcomeScreenIfAccountEmpty() {
|
||||||
|
guard accounts.isEmpty else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
navigation.presentingWelcomeScreen = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ContentView_Previews: PreviewProvider {
|
struct ContentView_Previews: PreviewProvider {
|
||||||
|
@ -7,6 +7,7 @@ struct Sidebar: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
ScrollViewReader { scrollView in
|
ScrollViewReader { scrollView in
|
||||||
List {
|
List {
|
||||||
|
if !accounts.isEmpty {
|
||||||
mainNavigationLinks
|
mainNavigationLinks
|
||||||
|
|
||||||
AppSidebarRecents()
|
AppSidebarRecents()
|
||||||
@ -17,6 +18,7 @@ struct Sidebar: View {
|
|||||||
AppSidebarPlaylists()
|
AppSidebarPlaylists()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.onChange(of: navigation.sidebarSectionChanged) { _ in
|
.onChange(of: navigation.sidebarSectionChanged) { _ in
|
||||||
scrollScrollViewToItem(scrollView: scrollView, for: navigation.tabSelection)
|
scrollScrollViewToItem(scrollView: scrollView, for: navigation.tabSelection)
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,7 @@ struct PlaybackBar: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func availableStreamsForInstance(_ instance: Instance) -> [Stream.Kind: [Stream]] {
|
private func availableStreamsForInstance(_ instance: Instance) -> [Stream.Kind: [Stream]] {
|
||||||
let streams = player.availableStreams.filter { $0.instance == instance }.sorted(by: player.streamsSorter)
|
let streams = player.availableStreamsSorted.filter { $0.instance == instance }
|
||||||
|
|
||||||
return Dictionary(grouping: streams, by: \.kind!)
|
return Dictionary(grouping: streams, by: \.kind!)
|
||||||
}
|
}
|
||||||
|
@ -36,17 +36,23 @@ struct Player: UIViewControllerRepresentable {
|
|||||||
#if os(tvOS)
|
#if os(tvOS)
|
||||||
var streamingQualityMenu: UIMenu {
|
var streamingQualityMenu: UIMenu {
|
||||||
UIMenu(
|
UIMenu(
|
||||||
title: "Streaming quality",
|
title: "Streams",
|
||||||
image: UIImage(systemName: "antenna.radiowaves.left.and.right"),
|
image: UIImage(systemName: "antenna.radiowaves.left.and.right"),
|
||||||
children: streamingQualityMenuActions
|
children: streamingQualityMenuActions
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
var streamingQualityMenuActions: [UIAction] {
|
var streamingQualityMenuActions: [UIAction] {
|
||||||
player.availableStreamsSorted.map { stream in
|
guard !player.availableStreams.isEmpty else {
|
||||||
let image = player.streamSelection == stream ? UIImage(systemName: "checkmark") : nil
|
return [ // swiftlint:disable:this implicit_return
|
||||||
|
UIAction(title: "Empty", attributes: .disabled) { _ in }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
return UIAction(title: stream.description, image: image) { _ in
|
return player.availableStreamsSorted.map { stream in
|
||||||
|
let state = player.streamSelection == stream ? UIAction.State.on : .off
|
||||||
|
|
||||||
|
return UIAction(title: stream.description, state: state) { _ in
|
||||||
self.player.streamSelection = stream
|
self.player.streamSelection = stream
|
||||||
self.player.upgradeToStream(stream)
|
self.player.upgradeToStream(stream)
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import SwiftUI
|
|||||||
struct InstancesSettingsView: View {
|
struct InstancesSettingsView: View {
|
||||||
@Default(.instances) private var instances
|
@Default(.instances) private var instances
|
||||||
|
|
||||||
@EnvironmentObject<InvidiousAPI> private var api
|
@EnvironmentObject<AccountsModel> private var accounts
|
||||||
@EnvironmentObject<InstancesModel> private var instancesModel
|
@EnvironmentObject<InstancesModel> private var instancesModel
|
||||||
@EnvironmentObject<SubscriptionsModel> private var subscriptions
|
@EnvironmentObject<SubscriptionsModel> private var subscriptions
|
||||||
@EnvironmentObject<PlaylistsModel> private var playlists
|
@EnvironmentObject<PlaylistsModel> private var playlists
|
||||||
@ -55,6 +55,9 @@ struct InstancesSettingsView: View {
|
|||||||
|
|
||||||
private func removeInstanceButton(_ instance: Instance) -> some View {
|
private func removeInstanceButton(_ instance: Instance) -> some View {
|
||||||
Button("Remove", role: .destructive) {
|
Button("Remove", role: .destructive) {
|
||||||
|
if accounts.account?.instance == instance {
|
||||||
|
accounts.setAccount(nil)
|
||||||
|
}
|
||||||
instancesModel.remove(instance)
|
instancesModel.remove(instance)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
27
Shared/Views/OpenSettingsButton.swift
Normal file
27
Shared/Views/OpenSettingsButton.swift
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct OpenSettingsButton: View {
|
||||||
|
@Environment(\.dismiss) private var dismiss
|
||||||
|
@EnvironmentObject<NavigationModel> private var navigation
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
Button {
|
||||||
|
dismiss()
|
||||||
|
|
||||||
|
#if os(macOS)
|
||||||
|
NSApp.sendAction(Selector(("showPreferencesWindow:")), to: nil, from: nil)
|
||||||
|
#else
|
||||||
|
navigation.presentingSettings = true
|
||||||
|
#endif
|
||||||
|
} label: {
|
||||||
|
Label("Open Settings", systemImage: "gearshape.2")
|
||||||
|
}
|
||||||
|
.buttonStyle(.borderedProminent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct OpenSettingsButton_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
OpenSettingsButton()
|
||||||
|
}
|
||||||
|
}
|
@ -50,29 +50,16 @@ struct SignInRequiredView<Content: View>: View {
|
|||||||
|
|
||||||
#if !os(tvOS)
|
#if !os(tvOS)
|
||||||
if instances.isEmpty {
|
if instances.isEmpty {
|
||||||
openSettingsButton
|
OpenSettingsButton()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if os(tvOS)
|
#if os(tvOS)
|
||||||
openSettingsButton
|
OpenSettingsButton()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
.frame(minWidth: 0, maxWidth: .infinity, alignment: .center)
|
.frame(minWidth: 0, maxWidth: .infinity, alignment: .center)
|
||||||
}
|
}
|
||||||
|
|
||||||
var openSettingsButton: some View {
|
|
||||||
Button(action: {
|
|
||||||
#if os(macOS)
|
|
||||||
NSApp.sendAction(Selector(("showPreferencesWindow:")), to: nil, from: nil)
|
|
||||||
#else
|
|
||||||
navigation.presentingSettings = true
|
|
||||||
#endif
|
|
||||||
}) {
|
|
||||||
Text("Open Settings")
|
|
||||||
}
|
|
||||||
.buttonStyle(.borderedProminent)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SignInRequiredView_Previews: PreviewProvider {
|
struct SignInRequiredView_Previews: PreviewProvider {
|
||||||
|
63
Shared/Views/WelcomeScreen.swift
Normal file
63
Shared/Views/WelcomeScreen.swift
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct WelcomeScreen: View {
|
||||||
|
@Environment(\.dismiss) private var dismiss
|
||||||
|
|
||||||
|
@EnvironmentObject<AccountsModel> private var accounts
|
||||||
|
@EnvironmentObject<NavigationModel> private var navigation
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack {
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
Text("Welcome")
|
||||||
|
.font(.largeTitle)
|
||||||
|
.padding(.bottom, 10)
|
||||||
|
|
||||||
|
if accounts.all.isEmpty {
|
||||||
|
Text("To start, configure your Instances in Settings")
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
} else {
|
||||||
|
Text("To start, pick one of your accounts:")
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
#if os(tvOS)
|
||||||
|
AccountSelectionView(showHeader: false)
|
||||||
|
|
||||||
|
Button {
|
||||||
|
dismiss()
|
||||||
|
} label: {
|
||||||
|
Text("Start")
|
||||||
|
}
|
||||||
|
.opacity(accounts.account.isNil ? 0 : 1)
|
||||||
|
.disabled(accounts.account.isNil)
|
||||||
|
|
||||||
|
#else
|
||||||
|
AccountsMenuView()
|
||||||
|
.onChange(of: accounts.account) { _ in
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
#if os(macOS)
|
||||||
|
.frame(maxWidth: 280)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
OpenSettingsButton()
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.interactiveDismissDisabled()
|
||||||
|
#if os(macOS)
|
||||||
|
.frame(minWidth: 400, minHeight: 400)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct WelcomeScreen_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
WelcomeScreen()
|
||||||
|
.injectFixtureEnvironmentObjects()
|
||||||
|
}
|
||||||
|
}
|
@ -2,9 +2,6 @@ import Defaults
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct InstancesSettingsView: View {
|
struct InstancesSettingsView: View {
|
||||||
@Default(.instances) private var instances
|
|
||||||
@EnvironmentObject<InstancesModel> private var model
|
|
||||||
|
|
||||||
@State private var selectedInstanceID: Instance.ID?
|
@State private var selectedInstanceID: Instance.ID?
|
||||||
@State private var selectedAccount: Instance.Account?
|
@State private var selectedAccount: Instance.Account?
|
||||||
|
|
||||||
@ -14,6 +11,11 @@ struct InstancesSettingsView: View {
|
|||||||
|
|
||||||
@State private var presentingConfirmationDialog = false
|
@State private var presentingConfirmationDialog = false
|
||||||
|
|
||||||
|
@EnvironmentObject<AccountsModel> private var accounts
|
||||||
|
@EnvironmentObject<InstancesModel> private var model
|
||||||
|
|
||||||
|
@Default(.instances) private var instances
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Section {
|
Section {
|
||||||
Text("Instance")
|
Text("Instance")
|
||||||
@ -34,11 +36,11 @@ struct InstancesSettingsView: View {
|
|||||||
if !selectedInstance.isNil, selectedInstance.supportsAccounts {
|
if !selectedInstance.isNil, selectedInstance.supportsAccounts {
|
||||||
Text("Accounts")
|
Text("Accounts")
|
||||||
List(selection: $selectedAccount) {
|
List(selection: $selectedAccount) {
|
||||||
if accounts.isEmpty {
|
if selectedInstanceAccounts.isEmpty {
|
||||||
Text("You have no accounts for this instance")
|
Text("You have no accounts for this instance")
|
||||||
.foregroundColor(.secondary)
|
.foregroundColor(.secondary)
|
||||||
}
|
}
|
||||||
ForEach(accounts) { account in
|
ForEach(selectedInstanceAccounts) { account in
|
||||||
AccountSettingsView(account: account, selectedAccount: $selectedAccount)
|
AccountSettingsView(account: account, selectedAccount: $selectedAccount)
|
||||||
.tag(account)
|
.tag(account)
|
||||||
}
|
}
|
||||||
@ -73,6 +75,10 @@ struct InstancesSettingsView: View {
|
|||||||
isPresented: $presentingConfirmationDialog
|
isPresented: $presentingConfirmationDialog
|
||||||
) {
|
) {
|
||||||
Button("Remove Instance", role: .destructive) {
|
Button("Remove Instance", role: .destructive) {
|
||||||
|
if accounts.account?.instance == selectedInstance {
|
||||||
|
accounts.setAccount(nil)
|
||||||
|
}
|
||||||
|
|
||||||
model.remove(selectedInstance!)
|
model.remove(selectedInstance!)
|
||||||
selectedInstanceID = instances.last?.id
|
selectedInstanceID = instances.last?.id
|
||||||
}
|
}
|
||||||
@ -113,7 +119,7 @@ struct InstancesSettingsView: View {
|
|||||||
model.find(selectedInstanceID)
|
model.find(selectedInstanceID)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var accounts: [Instance.Account] {
|
private var selectedInstanceAccounts: [Instance.Account] {
|
||||||
guard selectedInstance != nil else {
|
guard selectedInstance != nil else {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
@ -3,13 +3,15 @@ import Foundation
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct AccountSelectionView: View {
|
struct AccountSelectionView: View {
|
||||||
|
var showHeader = true
|
||||||
|
|
||||||
@EnvironmentObject<InstancesModel> private var instancesModel
|
@EnvironmentObject<InstancesModel> private var instancesModel
|
||||||
@EnvironmentObject<AccountsModel> private var accounts
|
@EnvironmentObject<AccountsModel> private var accounts
|
||||||
|
|
||||||
@Default(.instances) private var instances
|
@Default(.instances) private var instances
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Section(header: Text("Current Account")) {
|
Section(header: Text(showHeader ? "Current Account" : "")) {
|
||||||
Button(accountButtonTitle(account: accounts.account)) {
|
Button(accountButtonTitle(account: accounts.account)) {
|
||||||
if let account = nextAccount {
|
if let account = nextAccount {
|
||||||
accounts.setAccount(account)
|
accounts.setAccount(account)
|
||||||
|
Loading…
Reference in New Issue
Block a user