mirror of
https://github.com/yattee/yattee.git
synced 2026-07-20 14:22:02 +00:00
Fix layout jump when subscriptions sidebar appears after load on macOS
Load local-account subscriptions synchronously on appear so the channels sidebar is present in the first layout pass, and reserve the sidebar column with a spinner while async loads are in flight (gated by a persisted flag so users without enough channels never see a phantom column).
This commit is contained in:
@@ -38,6 +38,9 @@ struct SubscriptionsView: View {
|
|||||||
@AppStorage("subscriptionsHideWatched") private var hideWatched = false
|
@AppStorage("subscriptionsHideWatched") private var hideWatched = false
|
||||||
@AppStorage("subscriptionsChannelStripSize") private var channelStripSize: ChannelStripSize = .normal
|
@AppStorage("subscriptionsChannelStripSize") private var channelStripSize: ChannelStripSize = .normal
|
||||||
@AppStorage("subscriptionsShowSidebar") private var showSidebar = true
|
@AppStorage("subscriptionsShowSidebar") private var showSidebar = true
|
||||||
|
/// Whether the last completed load produced enough channels for the sidebar,
|
||||||
|
/// so its space can be reserved before the next load finishes.
|
||||||
|
@AppStorage("subscriptionsSidebarExpected") private var sidebarExpected = false
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
@AppStorage("subscriptionsMacOSSidebarWidth") private var macOSSidebarWidth = 240.0
|
@AppStorage("subscriptionsMacOSSidebarWidth") private var macOSSidebarWidth = 240.0
|
||||||
@State private var macOSSidebarDragStartWidth: Double?
|
@State private var macOSSidebarDragStartWidth: Double?
|
||||||
@@ -364,6 +367,11 @@ struct SubscriptionsView: View {
|
|||||||
macOSChannelsSidebar
|
macOSChannelsSidebar
|
||||||
.frame(width: clampedMacOSSidebarWidth)
|
.frame(width: clampedMacOSSidebarWidth)
|
||||||
|
|
||||||
|
macOSSidebarResizeHandle
|
||||||
|
} else if showSidebar && !subscriptionsLoaded && sidebarExpected {
|
||||||
|
macOSSidebarPlaceholder
|
||||||
|
.frame(width: clampedMacOSSidebarWidth)
|
||||||
|
|
||||||
macOSSidebarResizeHandle
|
macOSSidebarResizeHandle
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -476,6 +484,11 @@ struct SubscriptionsView: View {
|
|||||||
.liquidGlassSheetContent(sourceID: "subscriptionsViewOptions", in: sheetTransition)
|
.liquidGlassSheetContent(sourceID: "subscriptionsViewOptions", in: sheetTransition)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
.onAppear {
|
||||||
|
// Synchronous load for local accounts so the sidebar is
|
||||||
|
// present in the first layout pass (avoids layout jump).
|
||||||
|
loadSubscriptions()
|
||||||
|
}
|
||||||
.task {
|
.task {
|
||||||
await loadSubscriptionsAsync()
|
await loadSubscriptionsAsync()
|
||||||
loadWatchEntries()
|
loadWatchEntries()
|
||||||
@@ -934,6 +947,12 @@ struct SubscriptionsView: View {
|
|||||||
.scrollContentBackground(.hidden)
|
.scrollContentBackground(.hidden)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var macOSSidebarPlaceholder: some View {
|
||||||
|
ProgressView()
|
||||||
|
.controlSize(.small)
|
||||||
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
|
}
|
||||||
|
|
||||||
private var macOSSidebarResizeHandle: some View {
|
private var macOSSidebarResizeHandle: some View {
|
||||||
ZStack {
|
ZStack {
|
||||||
Rectangle()
|
Rectangle()
|
||||||
@@ -1299,6 +1318,7 @@ struct SubscriptionsView: View {
|
|||||||
if appEnvironment?.settingsManager.subscriptionAccount.type == .local {
|
if appEnvironment?.settingsManager.subscriptionAccount.type == .local {
|
||||||
subscriptions = dataManager?.subscriptions() ?? []
|
subscriptions = dataManager?.subscriptions() ?? []
|
||||||
subscriptionsLoaded = true
|
subscriptionsLoaded = true
|
||||||
|
sidebarExpected = subscriptions.count > 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if let selectedID = selectedChannelID,
|
if let selectedID = selectedChannelID,
|
||||||
@@ -1316,6 +1336,7 @@ struct SubscriptionsView: View {
|
|||||||
if appEnvironment.settingsManager.subscriptionAccount.type == .local {
|
if appEnvironment.settingsManager.subscriptionAccount.type == .local {
|
||||||
subscriptions = dataManager?.subscriptions() ?? []
|
subscriptions = dataManager?.subscriptions() ?? []
|
||||||
subscriptionsLoaded = true
|
subscriptionsLoaded = true
|
||||||
|
sidebarExpected = subscriptions.count > 1
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1325,6 +1346,7 @@ struct SubscriptionsView: View {
|
|||||||
// Convert channels to Subscription objects for UI (not persisted)
|
// Convert channels to Subscription objects for UI (not persisted)
|
||||||
subscriptions = channels.map { Subscription.from(channel: $0) }
|
subscriptions = channels.map { Subscription.from(channel: $0) }
|
||||||
subscriptionsLoaded = true
|
subscriptionsLoaded = true
|
||||||
|
sidebarExpected = subscriptions.count > 1
|
||||||
} catch {
|
} catch {
|
||||||
LoggingService.shared.error(
|
LoggingService.shared.error(
|
||||||
"Failed to load subscriptions: \(error.localizedDescription)",
|
"Failed to load subscriptions: \(error.localizedDescription)",
|
||||||
@@ -1332,6 +1354,7 @@ struct SubscriptionsView: View {
|
|||||||
)
|
)
|
||||||
subscriptions = []
|
subscriptions = []
|
||||||
subscriptionsLoaded = true
|
subscriptionsLoaded = true
|
||||||
|
sidebarExpected = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user