Adds multi-select to macOS sidebar
This hacks around property observers to get to a model that almost works.
This commit is contained in:
parent
2e94ae9e8e
commit
af4849642c
|
@ -20,6 +20,8 @@ class SidebarModel: ObservableObject {
|
||||||
|
|
||||||
@Published var sidebarItems = [SidebarItem]()
|
@Published var sidebarItems = [SidebarItem]()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidInitialize(_:)), name: .UnreadCountDidInitialize, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidInitialize(_:)), name: .UnreadCountDidInitialize, object: nil)
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(containerChildrenDidChange(_:)), name: .ChildrenDidChange, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(containerChildrenDidChange(_:)), name: .ChildrenDidChange, object: nil)
|
||||||
|
@ -62,7 +64,6 @@ class SidebarModel: ObservableObject {
|
||||||
|
|
||||||
sidebarItems = items
|
sidebarItems = items
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Private
|
// MARK: Private
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
//
|
||||||
|
// SidebarSelectionModel.swift
|
||||||
|
// NetNewsWire
|
||||||
|
//
|
||||||
|
// Created by Stuart Breckenridge on 8/7/20.
|
||||||
|
// Copyright © 2020 Ranchero Software. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import RSCore
|
||||||
|
import Account
|
||||||
|
|
||||||
|
|
||||||
|
class SidebarSelectionModel: ObservableObject {
|
||||||
|
#if os(macOS)
|
||||||
|
@Published var selectedSidebarItems = Set<FeedIdentifier>() {
|
||||||
|
didSet {
|
||||||
|
print(selectedSidebarItems)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private var items = Set<FeedIdentifier>()
|
||||||
|
|
||||||
|
@Published var selectedSidebarItem: FeedIdentifier? = .none {
|
||||||
|
willSet {
|
||||||
|
if newValue != nil {
|
||||||
|
items.insert(newValue!)
|
||||||
|
} else {
|
||||||
|
selectedSidebarItems = items
|
||||||
|
items.removeAll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,54 +12,74 @@ import Account
|
||||||
struct SidebarView: View {
|
struct SidebarView: View {
|
||||||
|
|
||||||
// I had to comment out SceneStorage because it blows up if used on macOS
|
// I had to comment out SceneStorage because it blows up if used on macOS
|
||||||
// @SceneStorage("expandedContainers") private var expandedContainerData = Data()
|
// @SceneStorage("expandedContainers") private var expandedContainerData = Data()
|
||||||
@StateObject private var expandedContainers = SidebarExpandedContainers()
|
@StateObject private var expandedContainers = SidebarExpandedContainers()
|
||||||
@EnvironmentObject private var sidebarModel: SidebarModel
|
@EnvironmentObject private var sidebarModel: SidebarModel
|
||||||
|
|
||||||
|
@StateObject private var sidebarSelectionModel = SidebarSelectionModel()
|
||||||
|
|
||||||
|
@ViewBuilder
|
||||||
var body: some View {
|
var body: some View {
|
||||||
List() {
|
#if os(macOS)
|
||||||
ForEach(sidebarModel.sidebarItems) { sidebarItem in
|
List(selection: $sidebarSelectionModel.selectedSidebarItems) {
|
||||||
if let containerID = sidebarItem.containerID {
|
containedList
|
||||||
DisclosureGroup(isExpanded: $expandedContainers[containerID]) {
|
}
|
||||||
ForEach(sidebarItem.children) { sidebarItem in
|
#else
|
||||||
if let containerID = sidebarItem.containerID {
|
List {
|
||||||
DisclosureGroup(isExpanded: $expandedContainers[containerID]) {
|
containedList
|
||||||
ForEach(sidebarItem.children) { sidebarItem in
|
}
|
||||||
ZStack {
|
#endif
|
||||||
SidebarItemView(sidebarItem: sidebarItem)
|
// .onAppear {
|
||||||
NavigationLink(destination: (TimelineContainerView(feed: sidebarItem.feed))) {
|
// expandedContainers.data = expandedContainerData
|
||||||
EmptyView()
|
// }
|
||||||
}.buttonStyle(PlainButtonStyle())
|
// .onReceive(expandedContainers.objectDidChange) {
|
||||||
}
|
// expandedContainerData = expandedContainers.data
|
||||||
}
|
// }
|
||||||
} label: {
|
}
|
||||||
|
|
||||||
|
var containedList: some View {
|
||||||
|
ForEach(sidebarModel.sidebarItems) { sidebarItem in
|
||||||
|
if let containerID = sidebarItem.containerID {
|
||||||
|
DisclosureGroup(isExpanded: $expandedContainers[containerID]) {
|
||||||
|
ForEach(sidebarItem.children) { sidebarItem in
|
||||||
|
if let containerID = sidebarItem.containerID {
|
||||||
|
DisclosureGroup(isExpanded: $expandedContainers[containerID]) {
|
||||||
|
ForEach(sidebarItem.children) { sidebarItem in
|
||||||
ZStack {
|
ZStack {
|
||||||
SidebarItemView(sidebarItem: sidebarItem)
|
SidebarItemView(sidebarItem: sidebarItem)
|
||||||
NavigationLink(destination: (TimelineContainerView(feed: sidebarItem.feed))) {
|
NavigationLink(destination: (TimelineContainerView(feed: sidebarItem.feed)),
|
||||||
|
tag: sidebarItem.feed!.feedID!,
|
||||||
|
selection: $sidebarSelectionModel.selectedSidebarItem) {
|
||||||
EmptyView()
|
EmptyView()
|
||||||
}.buttonStyle(PlainButtonStyle())
|
}.buttonStyle(PlainButtonStyle())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} label: {
|
||||||
ZStack {
|
ZStack {
|
||||||
SidebarItemView(sidebarItem: sidebarItem)
|
SidebarItemView(sidebarItem: sidebarItem)
|
||||||
NavigationLink(destination: (TimelineContainerView(feed: sidebarItem.feed))) {
|
NavigationLink(destination: (TimelineContainerView(feed: sidebarItem.feed)),
|
||||||
|
tag: sidebarItem.feed!.feedID!,
|
||||||
|
selection: $sidebarSelectionModel.selectedSidebarItem) {
|
||||||
EmptyView()
|
EmptyView()
|
||||||
}.buttonStyle(PlainButtonStyle())
|
}.buttonStyle(PlainButtonStyle())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
ZStack {
|
||||||
|
SidebarItemView(sidebarItem: sidebarItem)
|
||||||
|
NavigationLink(destination: (TimelineContainerView(feed: sidebarItem.feed)),
|
||||||
|
tag: sidebarItem.feed!.feedID!,
|
||||||
|
selection: $sidebarSelectionModel.selectedSidebarItem) {
|
||||||
|
EmptyView()
|
||||||
|
}.buttonStyle(PlainButtonStyle())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} label: {
|
|
||||||
SidebarItemView(sidebarItem: sidebarItem)
|
|
||||||
}
|
}
|
||||||
|
} label: {
|
||||||
|
SidebarItemView(sidebarItem: sidebarItem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// .onAppear {
|
|
||||||
// expandedContainers.data = expandedContainerData
|
|
||||||
// }
|
|
||||||
// .onReceive(expandedContainers.objectDidChange) {
|
|
||||||
// expandedContainerData = expandedContainers.data
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
1729529B24AA1FD200D65E66 /* MacSearchField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1729529A24AA1FD200D65E66 /* MacSearchField.swift */; };
|
1729529B24AA1FD200D65E66 /* MacSearchField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1729529A24AA1FD200D65E66 /* MacSearchField.swift */; };
|
||||||
175942AA24AD533200585066 /* RefreshInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE4226F4DFA0010922C /* RefreshInterval.swift */; };
|
175942AA24AD533200585066 /* RefreshInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE4226F4DFA0010922C /* RefreshInterval.swift */; };
|
||||||
175942AB24AD533200585066 /* RefreshInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE4226F4DFA0010922C /* RefreshInterval.swift */; };
|
175942AB24AD533200585066 /* RefreshInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE4226F4DFA0010922C /* RefreshInterval.swift */; };
|
||||||
|
1770CAFA24B5CFEC007D398B /* SidebarSelectionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1770CAF924B5CFEC007D398B /* SidebarSelectionModel.swift */; };
|
||||||
|
1770CAFB24B5CFEC007D398B /* SidebarSelectionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1770CAF924B5CFEC007D398B /* SidebarSelectionModel.swift */; };
|
||||||
1776E88E24AC5F8A00E78166 /* AppDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1776E88D24AC5F8A00E78166 /* AppDefaults.swift */; };
|
1776E88E24AC5F8A00E78166 /* AppDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1776E88D24AC5F8A00E78166 /* AppDefaults.swift */; };
|
||||||
1776E88F24AC5F8A00E78166 /* AppDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1776E88D24AC5F8A00E78166 /* AppDefaults.swift */; };
|
1776E88F24AC5F8A00E78166 /* AppDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1776E88D24AC5F8A00E78166 /* AppDefaults.swift */; };
|
||||||
17930ED424AF10EE00A9BA52 /* AddWebFeedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17930ED324AF10EE00A9BA52 /* AddWebFeedView.swift */; };
|
17930ED424AF10EE00A9BA52 /* AddWebFeedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17930ED324AF10EE00A9BA52 /* AddWebFeedView.swift */; };
|
||||||
|
@ -1769,6 +1771,7 @@
|
||||||
1729529224AA1CAA00D65E66 /* GeneralPreferencesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneralPreferencesView.swift; sourceTree = "<group>"; };
|
1729529224AA1CAA00D65E66 /* GeneralPreferencesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneralPreferencesView.swift; sourceTree = "<group>"; };
|
||||||
1729529624AA1CD000D65E66 /* MacPreferencesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MacPreferencesView.swift; sourceTree = "<group>"; };
|
1729529624AA1CD000D65E66 /* MacPreferencesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MacPreferencesView.swift; sourceTree = "<group>"; };
|
||||||
1729529A24AA1FD200D65E66 /* MacSearchField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MacSearchField.swift; sourceTree = "<group>"; };
|
1729529A24AA1FD200D65E66 /* MacSearchField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MacSearchField.swift; sourceTree = "<group>"; };
|
||||||
|
1770CAF924B5CFEC007D398B /* SidebarSelectionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarSelectionModel.swift; sourceTree = "<group>"; };
|
||||||
1776E88D24AC5F8A00E78166 /* AppDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDefaults.swift; sourceTree = "<group>"; };
|
1776E88D24AC5F8A00E78166 /* AppDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDefaults.swift; sourceTree = "<group>"; };
|
||||||
17930ED324AF10EE00A9BA52 /* AddWebFeedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddWebFeedView.swift; sourceTree = "<group>"; };
|
17930ED324AF10EE00A9BA52 /* AddWebFeedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddWebFeedView.swift; sourceTree = "<group>"; };
|
||||||
179DBBA2B22A659F81EED6F9 /* AccountsNewsBlurWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountsNewsBlurWindowController.swift; sourceTree = "<group>"; };
|
179DBBA2B22A659F81EED6F9 /* AccountsNewsBlurWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountsNewsBlurWindowController.swift; sourceTree = "<group>"; };
|
||||||
|
@ -3090,6 +3093,7 @@
|
||||||
17D5F17024B0BC6700375168 /* SidebarToolbarModel.swift */,
|
17D5F17024B0BC6700375168 /* SidebarToolbarModel.swift */,
|
||||||
172199F024AB716900A31D04 /* SidebarToolbarModifier.swift */,
|
172199F024AB716900A31D04 /* SidebarToolbarModifier.swift */,
|
||||||
51919FA524AA64B000541E64 /* SidebarView.swift */,
|
51919FA524AA64B000541E64 /* SidebarView.swift */,
|
||||||
|
1770CAF924B5CFEC007D398B /* SidebarSelectionModel.swift */,
|
||||||
51919FAB24AA8CCA00541E64 /* UnreadCountView.swift */,
|
51919FAB24AA8CCA00541E64 /* UnreadCountView.swift */,
|
||||||
);
|
);
|
||||||
path = Sidebar;
|
path = Sidebar;
|
||||||
|
@ -4098,46 +4102,46 @@
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
51314636235A7BBE00387FDC = {
|
51314636235A7BBE00387FDC = {
|
||||||
CreatedOnToolsVersion = 11.2;
|
CreatedOnToolsVersion = 11.2;
|
||||||
DevelopmentTeam = SHJK2V3AJG;
|
DevelopmentTeam = FQLBNX3GP7;
|
||||||
LastSwiftMigration = 1120;
|
LastSwiftMigration = 1120;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
};
|
};
|
||||||
513C5CE5232571C2003D4054 = {
|
513C5CE5232571C2003D4054 = {
|
||||||
CreatedOnToolsVersion = 11.0;
|
CreatedOnToolsVersion = 11.0;
|
||||||
DevelopmentTeam = SHJK2V3AJG;
|
DevelopmentTeam = FQLBNX3GP7;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
};
|
};
|
||||||
518B2ED12351B3DD00400001 = {
|
518B2ED12351B3DD00400001 = {
|
||||||
CreatedOnToolsVersion = 11.2;
|
CreatedOnToolsVersion = 11.2;
|
||||||
DevelopmentTeam = SHJK2V3AJG;
|
DevelopmentTeam = FQLBNX3GP7;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
TestTargetID = 840D617B2029031C009BC708;
|
TestTargetID = 840D617B2029031C009BC708;
|
||||||
};
|
};
|
||||||
51C0513C24A77DF800194D5E = {
|
51C0513C24A77DF800194D5E = {
|
||||||
CreatedOnToolsVersion = 12.0;
|
CreatedOnToolsVersion = 12.0;
|
||||||
DevelopmentTeam = SHJK2V3AJG;
|
DevelopmentTeam = FQLBNX3GP7;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
};
|
};
|
||||||
51C0514324A77DF800194D5E = {
|
51C0514324A77DF800194D5E = {
|
||||||
CreatedOnToolsVersion = 12.0;
|
CreatedOnToolsVersion = 12.0;
|
||||||
DevelopmentTeam = SHJK2V3AJG;
|
DevelopmentTeam = FQLBNX3GP7;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
};
|
};
|
||||||
6581C73220CED60000F4AD34 = {
|
6581C73220CED60000F4AD34 = {
|
||||||
DevelopmentTeam = SHJK2V3AJG;
|
DevelopmentTeam = FQLBNX3GP7;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
};
|
};
|
||||||
65ED3FA2235DEF6C0081F399 = {
|
65ED3FA2235DEF6C0081F399 = {
|
||||||
DevelopmentTeam = SHJK2V3AJG;
|
DevelopmentTeam = FQLBNX3GP7;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
};
|
};
|
||||||
65ED4090235DEF770081F399 = {
|
65ED4090235DEF770081F399 = {
|
||||||
DevelopmentTeam = SHJK2V3AJG;
|
DevelopmentTeam = FQLBNX3GP7;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
};
|
};
|
||||||
840D617B2029031C009BC708 = {
|
840D617B2029031C009BC708 = {
|
||||||
CreatedOnToolsVersion = 9.3;
|
CreatedOnToolsVersion = 9.3;
|
||||||
DevelopmentTeam = SHJK2V3AJG;
|
DevelopmentTeam = FQLBNX3GP7;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
SystemCapabilities = {
|
SystemCapabilities = {
|
||||||
com.apple.BackgroundModes = {
|
com.apple.BackgroundModes = {
|
||||||
|
@ -4147,7 +4151,7 @@
|
||||||
};
|
};
|
||||||
849C645F1ED37A5D003D8FC0 = {
|
849C645F1ED37A5D003D8FC0 = {
|
||||||
CreatedOnToolsVersion = 8.2.1;
|
CreatedOnToolsVersion = 8.2.1;
|
||||||
DevelopmentTeam = SHJK2V3AJG;
|
DevelopmentTeam = FQLBNX3GP7;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
SystemCapabilities = {
|
SystemCapabilities = {
|
||||||
com.apple.HardenedRuntime = {
|
com.apple.HardenedRuntime = {
|
||||||
|
@ -4157,7 +4161,7 @@
|
||||||
};
|
};
|
||||||
849C64701ED37A5D003D8FC0 = {
|
849C64701ED37A5D003D8FC0 = {
|
||||||
CreatedOnToolsVersion = 8.2.1;
|
CreatedOnToolsVersion = 8.2.1;
|
||||||
DevelopmentTeam = SHJK2V3AJG;
|
DevelopmentTeam = FQLBNX3GP7;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
TestTargetID = 849C645F1ED37A5D003D8FC0;
|
TestTargetID = 849C645F1ED37A5D003D8FC0;
|
||||||
};
|
};
|
||||||
|
@ -4982,6 +4986,7 @@
|
||||||
51E4991B24A8091000B667CB /* IconImage.swift in Sources */,
|
51E4991B24A8091000B667CB /* IconImage.swift in Sources */,
|
||||||
51E4995424A8734D00B667CB /* ExtensionPointIdentifer.swift in Sources */,
|
51E4995424A8734D00B667CB /* ExtensionPointIdentifer.swift in Sources */,
|
||||||
51E4996924A8760C00B667CB /* ArticleStylesManager.swift in Sources */,
|
51E4996924A8760C00B667CB /* ArticleStylesManager.swift in Sources */,
|
||||||
|
1770CAFA24B5CFEC007D398B /* SidebarSelectionModel.swift in Sources */,
|
||||||
5177471E24B387E100EB0F74 /* ImageTransition.swift in Sources */,
|
5177471E24B387E100EB0F74 /* ImageTransition.swift in Sources */,
|
||||||
51E498F324A8085D00B667CB /* PseudoFeed.swift in Sources */,
|
51E498F324A8085D00B667CB /* PseudoFeed.swift in Sources */,
|
||||||
51A5769624AE617200078888 /* ArticleContainerView.swift in Sources */,
|
51A5769624AE617200078888 /* ArticleContainerView.swift in Sources */,
|
||||||
|
@ -5094,6 +5099,7 @@
|
||||||
51E4990524A808C300B667CB /* FeaturedImageDownloader.swift in Sources */,
|
51E4990524A808C300B667CB /* FeaturedImageDownloader.swift in Sources */,
|
||||||
5181C5AE24AF89B1002E0F70 /* PreferredColorSchemeModifier.swift in Sources */,
|
5181C5AE24AF89B1002E0F70 /* PreferredColorSchemeModifier.swift in Sources */,
|
||||||
51E4991624A8090300B667CB /* ArticleUtilities.swift in Sources */,
|
51E4991624A8090300B667CB /* ArticleUtilities.swift in Sources */,
|
||||||
|
1770CAFB24B5CFEC007D398B /* SidebarSelectionModel.swift in Sources */,
|
||||||
51919FF224AB864A00541E64 /* TimelineModel.swift in Sources */,
|
51919FF224AB864A00541E64 /* TimelineModel.swift in Sources */,
|
||||||
51E4991A24A8090F00B667CB /* IconImage.swift in Sources */,
|
51E4991A24A8090F00B667CB /* IconImage.swift in Sources */,
|
||||||
51E4992724A80AAB00B667CB /* AppAssets.swift in Sources */,
|
51E4992724A80AAB00B667CB /* AppAssets.swift in Sources */,
|
||||||
|
|
Loading…
Reference in New Issue