Files
yattee/Yattee/Views/Subscriptions/SubscriptionsSidebarRow.swift
Arkadiusz Fal fe78261866 Add channels sidebar to Subscriptions on iPad regular width
On iPad in regular horizontal size class, the Subscriptions view now
shows a channels column next to the feed (mirroring macOS/tvOS) instead
of the floating channel strip. iPhone and compact-width iPad keep the
existing strip.

- Renames MacSubscriptionsSidebarRow to SubscriptionsSidebarRow and
  shares it across macOS and iOS.
- Uses a custom ScrollView-based sidebar on iPad to avoid iOS 26's
  sidebar background extension bleeding into the selection highlight.
- Forces inline toolbar title on iPad regular so scrolling either
  column behaves consistently.
2026-04-19 17:48:17 +02:00

78 lines
2.2 KiB
Swift

//
// SubscriptionsSidebarRow.swift
// Yattee
//
// Compact row used in the Subscriptions sidebar (macOS and iPad) for the
// "All Channels" entry and each subscribed channel.
//
import SwiftUI
import NukeUI
struct SubscriptionsSidebarRow: View {
let name: String
let avatarURL: URL?
let serverURL: URL?
let authHeader: String?
let channelID: String?
let isAllChannels: Bool
var isSelected: Bool = false
private let avatarSize: CGFloat = 28
private var effectiveAvatarURL: URL? {
guard let channelID else { return nil }
return AvatarURLBuilder.avatarURL(
channelID: channelID,
directURL: avatarURL,
serverURL: serverURL,
size: Int(avatarSize * 2)
)
}
var body: some View {
HStack(spacing: 8) {
avatar
.frame(width: avatarSize, height: avatarSize)
.clipShape(Circle())
Text(name)
.fontWeight(isSelected ? .semibold : .regular)
.lineLimit(1)
Spacer(minLength: 0)
}
.contentShape(Rectangle())
}
@ViewBuilder
private var avatar: some View {
if isAllChannels {
ZStack {
Circle().fill(.quaternary)
Image(systemName: "rectangle.stack.fill")
.resizable()
.aspectRatio(contentMode: .fit)
.foregroundStyle(.secondary)
.padding(avatarSize * 0.25)
}
} else {
LazyImage(request: AvatarURLBuilder.imageRequest(url: effectiveAvatarURL, authHeader: authHeader)) { state in
if let image = state.image {
image
.resizable()
.aspectRatio(contentMode: .fill)
} else {
Circle()
.fill(.quaternary)
.overlay {
Text(String(name.prefix(1)))
.font(.caption)
.foregroundStyle(.secondary)
}
}
}
}
}
}