mirror of
https://github.com/yattee/yattee.git
synced 2026-07-20 14:22:02 +00:00
Move channel tab picker to toolbar on macOS
Replace the centered avatar/name toolbar title with the About/Videos/Shorts/Streams/Playlists segmented picker. The channel avatar and name move to the leading edge next to the view options button, in their own glass capsule (sharedBackgroundVisibility(.hidden) + glassEffect on macOS 26). Add spacing between the channel banner and the content below now that the inline picker is gone.
This commit is contained in:
@@ -307,6 +307,14 @@ struct ChannelView: View {
|
|||||||
.id("channelTop")
|
.id("channelTop")
|
||||||
|
|
||||||
// Content based on instance type
|
// Content based on instance type
|
||||||
|
// On macOS the content type picker lives in the toolbar instead.
|
||||||
|
#if os(macOS)
|
||||||
|
// Breathing room between the banner and the content below.
|
||||||
|
Color.clear.frame(height: 16)
|
||||||
|
if !supportsChannelTabs {
|
||||||
|
channelDescription(channel)
|
||||||
|
}
|
||||||
|
#else
|
||||||
if supportsChannelTabs {
|
if supportsChannelTabs {
|
||||||
// Pill-style content type switcher
|
// Pill-style content type switcher
|
||||||
contentTypePicker
|
contentTypePicker
|
||||||
@@ -316,6 +324,7 @@ struct ChannelView: View {
|
|||||||
// Non-tab instances: show description
|
// Non-tab instances: show description
|
||||||
channelDescription(channel)
|
channelDescription(channel)
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tab content or search results
|
// Tab content or search results
|
||||||
@@ -366,8 +375,11 @@ struct ChannelView: View {
|
|||||||
))
|
))
|
||||||
.toolbar {
|
.toolbar {
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
ToolbarItem(placement: .principal) {
|
if supportsChannelTabs && !(isSearchActive && hasSearched) {
|
||||||
collapsedToolbarTitle(name: channel.name, thumbnailURL: channel.thumbnailURL)
|
ToolbarItem(placement: .principal) {
|
||||||
|
contentTypePicker
|
||||||
|
.fixedSize()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
ToolbarItem(placement: .principal) {
|
ToolbarItem(placement: .principal) {
|
||||||
@@ -410,6 +422,22 @@ struct ChannelView: View {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// macOS: channel avatar + name sit on the leading edge, next to view
|
||||||
|
// options. Excluded from the shared glass background so the view
|
||||||
|
// options button keeps its own capsule and the title renders plain.
|
||||||
|
#if os(macOS)
|
||||||
|
if #available(macOS 26, *) {
|
||||||
|
ToolbarItem(placement: .navigation) {
|
||||||
|
collapsedToolbarTitle(name: channel.name, thumbnailURL: channel.thumbnailURL)
|
||||||
|
}
|
||||||
|
.sharedBackgroundVisibility(.hidden)
|
||||||
|
} else {
|
||||||
|
ToolbarItem(placement: .navigation) {
|
||||||
|
collapsedToolbarTitle(name: channel.name, thumbnailURL: channel.thumbnailURL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// iOS keeps a fixed gap between the trailing view options and channel
|
// iOS keeps a fixed gap between the trailing view options and channel
|
||||||
// menu buttons; on macOS view options moves to the leading edge, so no
|
// menu buttons; on macOS view options moves to the leading edge, so no
|
||||||
// gap is needed here.
|
// gap is needed here.
|
||||||
@@ -471,11 +499,16 @@ struct ChannelView: View {
|
|||||||
.id("channelTop")
|
.id("channelTop")
|
||||||
|
|
||||||
// Show tab picker during loading (doesn't depend on channel)
|
// Show tab picker during loading (doesn't depend on channel)
|
||||||
|
// On macOS the content type picker lives in the toolbar instead.
|
||||||
|
#if os(macOS)
|
||||||
|
Color.clear.frame(height: 16)
|
||||||
|
#else
|
||||||
if supportsChannelTabs {
|
if supportsChannelTabs {
|
||||||
contentTypePicker
|
contentTypePicker
|
||||||
.padding(.horizontal)
|
.padding(.horizontal)
|
||||||
.padding(.vertical, 8)
|
.padding(.vertical, 8)
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Centered spinner for content area below tabs
|
// Centered spinner for content area below tabs
|
||||||
ProgressView()
|
ProgressView()
|
||||||
@@ -491,8 +524,11 @@ struct ChannelView: View {
|
|||||||
.ignoresSafeArea(edges: .top)
|
.ignoresSafeArea(edges: .top)
|
||||||
.toolbar {
|
.toolbar {
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
ToolbarItem(placement: .principal) {
|
if supportsChannelTabs {
|
||||||
collapsedToolbarTitle(name: cached.name, thumbnailURL: cached.thumbnailURL)
|
ToolbarItem(placement: .principal) {
|
||||||
|
contentTypePicker
|
||||||
|
.fixedSize()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
ToolbarItem(placement: .principal) {
|
ToolbarItem(placement: .principal) {
|
||||||
@@ -535,6 +571,22 @@ struct ChannelView: View {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// macOS: channel avatar + name sit on the leading edge, next to view
|
||||||
|
// options. Excluded from the shared glass background so the view
|
||||||
|
// options button keeps its own capsule and the title renders plain.
|
||||||
|
#if os(macOS)
|
||||||
|
if #available(macOS 26, *) {
|
||||||
|
ToolbarItem(placement: .navigation) {
|
||||||
|
collapsedToolbarTitle(name: cached.name, thumbnailURL: cached.thumbnailURL)
|
||||||
|
}
|
||||||
|
.sharedBackgroundVisibility(.hidden)
|
||||||
|
} else {
|
||||||
|
ToolbarItem(placement: .navigation) {
|
||||||
|
collapsedToolbarTitle(name: cached.name, thumbnailURL: cached.thumbnailURL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// iOS keeps a fixed gap between the trailing view options and channel
|
// iOS keeps a fixed gap between the trailing view options and channel
|
||||||
// menu buttons; on macOS view options moves to the leading edge, so no
|
// menu buttons; on macOS view options moves to the leading edge, so no
|
||||||
// gap is needed here.
|
// gap is needed here.
|
||||||
@@ -865,8 +917,9 @@ struct ChannelView: View {
|
|||||||
// MARK: - Header
|
// MARK: - Header
|
||||||
|
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
|
@ViewBuilder
|
||||||
private func collapsedToolbarTitle(name: String, thumbnailURL: URL?) -> some View {
|
private func collapsedToolbarTitle(name: String, thumbnailURL: URL?) -> some View {
|
||||||
HStack(spacing: 8) {
|
let label = HStack(spacing: 8) {
|
||||||
LazyImage(url: thumbnailURL) { state in
|
LazyImage(url: thumbnailURL) { state in
|
||||||
if let image = state.image {
|
if let image = state.image {
|
||||||
image
|
image
|
||||||
@@ -885,6 +938,16 @@ struct ChannelView: View {
|
|||||||
.lineLimit(1)
|
.lineLimit(1)
|
||||||
}
|
}
|
||||||
.padding(.horizontal, 10)
|
.padding(.horizontal, 10)
|
||||||
|
|
||||||
|
// Own glass capsule; the toolbar item opts out of the shared background
|
||||||
|
// so this doesn't merge with the view options button.
|
||||||
|
if #available(macOS 26, *) {
|
||||||
|
label
|
||||||
|
.padding(.vertical, 5)
|
||||||
|
.glassEffect()
|
||||||
|
} else {
|
||||||
|
label
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user