Channels layout improvements, other UI fixes

This commit is contained in:
Arkadiusz Fal
2021-08-31 23:17:50 +02:00
parent 1651110a5d
commit b00b54ad2a
28 changed files with 633 additions and 192 deletions

View File

@@ -38,16 +38,27 @@ struct AppSidebarNavigation: View {
NavigationView {
sidebar
.frame(minWidth: 180)
Text("Select section")
}
}
var sidebar: some View {
List {
mainNavigationLinks
ScrollViewReader { scrollView in
List {
mainNavigationLinks
AppSidebarSubscriptions(selection: selection)
AppSidebarPlaylists(selection: selection)
Group {
AppSidebarRecentlyOpened(selection: selection)
.id("recentlyOpened")
AppSidebarSubscriptions(selection: selection)
AppSidebarPlaylists(selection: selection)
}
.onChange(of: navigationState.sidebarSectionChanged) { _ in
scrollScrollViewToItem(scrollView: scrollView, for: navigationState.tabSelection)
}
}
.listStyle(.sidebar)
}
#if os(macOS)
@@ -61,48 +72,51 @@ struct AppSidebarNavigation: View {
var mainNavigationLinks: some View {
Group {
NavigationLink(tag: TabSelection.subscriptions, selection: selection) {
SubscriptionsView()
}
label: {
NavigationLink(destination: SubscriptionsView(), tag: TabSelection.subscriptions, selection: selection) {
Label("Subscriptions", systemImage: "star.circle.fill")
.accessibility(label: Text("Subscriptions"))
}
NavigationLink(tag: TabSelection.popular, selection: selection) {
PopularView()
}
label: {
NavigationLink(destination: PopularView(), tag: TabSelection.popular, selection: selection) {
Label("Popular", systemImage: "chart.bar")
.accessibility(label: Text("Popular"))
}
NavigationLink(tag: TabSelection.trending, selection: selection) {
TrendingView()
}
label: {
NavigationLink(destination: TrendingView(), tag: TabSelection.trending, selection: selection) {
Label("Trending", systemImage: "chart.line.uptrend.xyaxis")
.accessibility(label: Text("Trending"))
}
NavigationLink(tag: TabSelection.playlists, selection: selection) {
PlaylistsView()
}
label: {
NavigationLink(destination: PlaylistsView(), tag: TabSelection.playlists, selection: selection) {
Label("Playlists", systemImage: "list.and.film")
.accessibility(label: Text("Playlists"))
}
NavigationLink(tag: TabSelection.search, selection: selection) {
SearchView()
}
label: {
NavigationLink(destination: SearchView(), tag: TabSelection.search, selection: selection) {
Label("Search", systemImage: "magnifyingglass")
.accessibility(label: Text("Search"))
}
}
}
func scrollScrollViewToItem(scrollView: ScrollViewProxy, for selection: TabSelection) {
if case let .channel(id) = selection {
if subscriptions.isSubscribing(id) {
scrollView.scrollTo(id)
} else {
scrollView.scrollTo("recentlyOpened")
}
} else if case let .playlist(id) = selection {
scrollView.scrollTo(id)
}
}
#if os(macOS)
private func toggleSidebar() {
NSApp.keyWindow?.contentViewController?.tryToPerform(#selector(NSSplitViewController.toggleSidebar(_:)), with: nil)
}
#endif
static func symbolSystemImage(_ name: String) -> String {
let firstLetter = name.first?.lowercased()
let regex = #"^[a-z0-9]$"#
@@ -111,10 +125,4 @@ struct AppSidebarNavigation: View {
return "\(symbolName).square"
}
#if os(macOS)
private func toggleSidebar() {
NSApp.keyWindow?.contentViewController?.tryToPerform(#selector(NSSplitViewController.toggleSidebar(_:)), with: nil)
}
#endif
}

View File

@@ -15,6 +15,7 @@ struct AppSidebarPlaylists: View {
Label(playlist.title, systemImage: AppSidebarNavigation.symbolSystemImage(playlist.title))
.badge(Text("\(playlist.videos.count)"))
}
.id(playlist.id)
.contextMenu {
Button("Edit") {
navigationState.presentEditPlaylistForm(playlists.find(id: playlist.id))

View File

@@ -0,0 +1,54 @@
import SwiftUI
struct AppSidebarRecentlyOpened: View {
@Binding var selection: TabSelection?
@EnvironmentObject<NavigationState> private var navigationState
@EnvironmentObject<Subscriptions> private var subscriptions
@State private var subscriptionsChanged = false
var body: some View {
Group {
if !recentlyOpened.isEmpty {
Section(header: Text("Recently Opened")) {
ForEach(recentlyOpened) { channel in
NavigationLink(tag: TabSelection.channel(channel.id), selection: $selection) {
ChannelVideosView(channel)
} label: {
HStack {
Label(channel.name, systemImage: AppSidebarNavigation.symbolSystemImage(channel.name))
Spacer()
Button(action: { navigationState.closeChannel(channel) }) {
Image(systemName: "xmark.circle.fill")
}
.foregroundColor(.secondary)
.buttonStyle(.plain)
}
}
// force recalculating the view on change of subscriptions
.opacity(subscriptionsChanged ? 1 : 1)
.id(channel.id)
.contextMenu {
Button("Subscribe") {
subscriptions.subscribe(channel.id) {
navigationState.sidebarSectionChanged.toggle()
}
}
}
}
}
.onChange(of: subscriptions.all) { _ in
subscriptionsChanged.toggle()
}
}
}
}
var recentlyOpened: [Channel] {
navigationState.openChannels.filter { !subscriptions.all.contains($0) }
}
}

View File

@@ -19,13 +19,7 @@ struct AppSidebarSubscriptions: View {
navigationState.presentUnsubscribeAlert(channel)
}
}
.alert(unsubscribeAlertTitle, isPresented: $navigationState.presentingUnsubscribeAlert) {
if let channel = navigationState.channelToUnsubscribe {
Button("Unsubscribe", role: .destructive) {
subscriptions.unsubscribe(channel.id)
}
}
}
.modifier(UnsubscribeAlertModifier())
}
}
}

View File

@@ -2,10 +2,10 @@ import Defaults
import SwiftUI
struct AppTabNavigation: View {
@State private var tabSelection: TabSelection = .subscriptions
@EnvironmentObject<NavigationState> private var navigationState
var body: some View {
TabView(selection: $tabSelection) {
TabView(selection: $navigationState.tabSelection) {
NavigationView {
SubscriptionsView()
}
@@ -51,5 +51,19 @@ struct AppTabNavigation: View {
}
.tag(TabSelection.search)
}
.sheet(isPresented: $navigationState.isChannelOpen, onDismiss: {
navigationState.closeChannel(presentedChannel)
}) {
if presentedChannel != nil {
NavigationView {
ChannelVideosView(presentedChannel)
.environment(\.inNavigationView, true)
}
}
}
}
fileprivate var presentedChannel: Channel! {
navigationState.openChannels.first
}
}