Animate sidebar item changes
This commit is contained in:
parent
b3ca806d0b
commit
36aba33c3d
@ -20,7 +20,8 @@ class SidebarModel: ObservableObject, UndoableCommandRunner {
|
|||||||
|
|
||||||
weak var delegate: SidebarModelDelegate?
|
weak var delegate: SidebarModelDelegate?
|
||||||
|
|
||||||
@Published var sidebarItems = [SidebarItem]()
|
var sidebarItemsPublisher: AnyPublisher<[SidebarItem], Never>?
|
||||||
|
|
||||||
@Published var selectedFeedIdentifiers = Set<FeedIdentifier>()
|
@Published var selectedFeedIdentifiers = Set<FeedIdentifier>()
|
||||||
@Published var selectedFeedIdentifier: FeedIdentifier? = .none
|
@Published var selectedFeedIdentifier: FeedIdentifier? = .none
|
||||||
@Published var selectedFeeds = [Feed]()
|
@Published var selectedFeeds = [Feed]()
|
||||||
@ -39,13 +40,13 @@ class SidebarModel: ObservableObject, UndoableCommandRunner {
|
|||||||
// MARK: API
|
// MARK: API
|
||||||
|
|
||||||
func goToNextUnread() {
|
func goToNextUnread() {
|
||||||
guard let startFeed = selectedFeeds.first ?? sidebarItems.first?.children.first?.feed else { return }
|
// guard let startFeed = selectedFeeds.first ?? sidebarItems.first?.children.first?.feed else { return }
|
||||||
|
//
|
||||||
if !goToNextUnread(startingAt: startFeed) {
|
// if !goToNextUnread(startingAt: startFeed) {
|
||||||
if let firstFeed = sidebarItems.first?.children.first?.feed {
|
// if let firstFeed = sidebarItems.first?.children.first?.feed {
|
||||||
goToNextUnread(startingAt: firstFeed)
|
// goToNextUnread(startingAt: firstFeed)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -179,13 +180,14 @@ private extension SidebarModel {
|
|||||||
|
|
||||||
let kickStarter = Notification(name: Notification.Name(rawValue: "Kick Starter"))
|
let kickStarter = Notification(name: Notification.Name(rawValue: "Kick Starter"))
|
||||||
|
|
||||||
sidebarRebuildPublishers
|
sidebarItemsPublisher = sidebarRebuildPublishers
|
||||||
.prepend(kickStarter)
|
.prepend(kickStarter)
|
||||||
.debounce(for: .milliseconds(500), scheduler: RunLoop.main)
|
.debounce(for: .milliseconds(500), scheduler: RunLoop.main)
|
||||||
.combineLatest($isReadFiltered, $selectedFeeds)
|
.combineLatest($isReadFiltered, $selectedFeeds)
|
||||||
.sink { [weak self] _, readFilter, selectedFeeds in
|
.compactMap { [weak self] _, readFilter, selectedFeeds in
|
||||||
self?.rebuildSidebarItems(isReadFiltered: readFilter, selectedFeeds: selectedFeeds)
|
self?.rebuildSidebarItems(isReadFiltered: readFilter, selectedFeeds: selectedFeeds)
|
||||||
}.store(in: &cancellables)
|
}
|
||||||
|
.eraseToAnyPublisher()
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Sidebar Building
|
// MARK: Sidebar Building
|
||||||
@ -198,9 +200,9 @@ private extension SidebarModel {
|
|||||||
return feeds.sorted(by: { $0.nameForDisplay.localizedStandardCompare($1.nameForDisplay) == .orderedAscending })
|
return feeds.sorted(by: { $0.nameForDisplay.localizedStandardCompare($1.nameForDisplay) == .orderedAscending })
|
||||||
}
|
}
|
||||||
|
|
||||||
func rebuildSidebarItems(isReadFiltered: Bool, selectedFeeds: [Feed]) {
|
func rebuildSidebarItems(isReadFiltered: Bool, selectedFeeds: [Feed]) -> [SidebarItem] {
|
||||||
guard let delegate = delegate else { return }
|
|
||||||
var items = [SidebarItem]()
|
var items = [SidebarItem]()
|
||||||
|
guard let delegate = delegate else { return items }
|
||||||
|
|
||||||
var smartFeedControllerItem = SidebarItem(SmartFeedsController.shared)
|
var smartFeedControllerItem = SidebarItem(SmartFeedsController.shared)
|
||||||
for feed in SmartFeedsController.shared.smartFeeds {
|
for feed in SmartFeedsController.shared.smartFeeds {
|
||||||
@ -238,7 +240,7 @@ private extension SidebarModel {
|
|||||||
items.append(accountItem)
|
items.append(accountItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
sidebarItems = items
|
return items
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK:
|
// MARK:
|
||||||
@ -252,38 +254,38 @@ private extension SidebarModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@discardableResult
|
// @discardableResult
|
||||||
func goToNextUnread(startingAt: Feed) -> Bool {
|
// func goToNextUnread(startingAt: Feed) -> Bool {
|
||||||
|
//
|
||||||
var foundStartFeed = false
|
// var foundStartFeed = false
|
||||||
var nextSidebarItem: SidebarItem? = nil
|
// var nextSidebarItem: SidebarItem? = nil
|
||||||
for section in sidebarItems {
|
// for section in sidebarItems {
|
||||||
if nextSidebarItem == nil {
|
// if nextSidebarItem == nil {
|
||||||
section.visit { sidebarItem in
|
// section.visit { sidebarItem in
|
||||||
if !foundStartFeed && sidebarItem.feed?.feedID == startingAt.feedID {
|
// if !foundStartFeed && sidebarItem.feed?.feedID == startingAt.feedID {
|
||||||
foundStartFeed = true
|
// foundStartFeed = true
|
||||||
return false
|
// return false
|
||||||
}
|
// }
|
||||||
if foundStartFeed && sidebarItem.unreadCount > 0 {
|
// if foundStartFeed && sidebarItem.unreadCount > 0 {
|
||||||
nextSidebarItem = sidebarItem
|
// nextSidebarItem = sidebarItem
|
||||||
return true
|
// return true
|
||||||
}
|
// }
|
||||||
return false
|
// return false
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if let nextFeedID = nextSidebarItem?.feed?.feedID {
|
// if let nextFeedID = nextSidebarItem?.feed?.feedID {
|
||||||
select(nextFeedID)
|
// select(nextFeedID)
|
||||||
return true
|
// return true
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return false
|
// return false
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
func select(_ feedID: FeedIdentifier) {
|
// func select(_ feedID: FeedIdentifier) {
|
||||||
selectedFeedIdentifiers = Set([feedID])
|
// selectedFeedIdentifiers = Set([feedID])
|
||||||
selectedFeedIdentifier = feedID
|
// selectedFeedIdentifier = feedID
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@ struct SidebarView: View {
|
|||||||
@EnvironmentObject private var sceneModel: SceneModel
|
@EnvironmentObject private var sceneModel: SceneModel
|
||||||
@EnvironmentObject private var sidebarModel: SidebarModel
|
@EnvironmentObject private var sidebarModel: SidebarModel
|
||||||
|
|
||||||
|
@State var sidebarItems = [SidebarItem]()
|
||||||
|
|
||||||
private let threshold: CGFloat = 80
|
private let threshold: CGFloat = 80
|
||||||
@State private var previousScrollOffset: CGFloat = 0
|
@State private var previousScrollOffset: CGFloat = 0
|
||||||
@State private var scrollOffset: CGFloat = 0
|
@State private var scrollOffset: CGFloat = 0
|
||||||
@ -64,6 +66,9 @@ struct SidebarView: View {
|
|||||||
.onAppear {
|
.onAppear {
|
||||||
sidebarModel.undoManager = undoManager
|
sidebarModel.undoManager = undoManager
|
||||||
}
|
}
|
||||||
|
.onReceive(sidebarModel.sidebarItemsPublisher!) { newItems in
|
||||||
|
sidebarItems = newItems
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
ZStack(alignment: .top) {
|
ZStack(alignment: .top) {
|
||||||
List {
|
List {
|
||||||
@ -81,6 +86,11 @@ struct SidebarView: View {
|
|||||||
.onAppear {
|
.onAppear {
|
||||||
sidebarModel.undoManager = undoManager
|
sidebarModel.undoManager = undoManager
|
||||||
}
|
}
|
||||||
|
.onReceive(sidebarModel.sidebarItemsPublisher!) { newItems in
|
||||||
|
withAnimation {
|
||||||
|
sidebarItems = newItems
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// .onAppear {
|
// .onAppear {
|
||||||
@ -148,7 +158,7 @@ struct SidebarView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var rows: some View {
|
var rows: some View {
|
||||||
ForEach(sidebarModel.sidebarItems) { sidebarItem in
|
ForEach(sidebarItems) { sidebarItem in
|
||||||
if let containerID = sidebarItem.containerID {
|
if let containerID = sidebarItem.containerID {
|
||||||
DisclosureGroup(isExpanded: $expandedContainers[containerID]) {
|
DisclosureGroup(isExpanded: $expandedContainers[containerID]) {
|
||||||
ForEach(sidebarItem.children) { sidebarItem in
|
ForEach(sidebarItem.children) { sidebarItem in
|
||||||
|
Loading…
x
Reference in New Issue
Block a user