Skip to content

Commit

Permalink
指南的list能够记录展开状态。
Browse files Browse the repository at this point in the history
  • Loading branch information
ming1016 committed Nov 19, 2024
1 parent 4545d36 commit f6a2e1e
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 98 deletions.
3 changes: 3 additions & 0 deletions SwiftPamphletApp/App/SwiftPamphletAppConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ struct SPC {
static let isShowWWDCInspector = "isShowWWDCInspector"
static let inspectorType = "inspectorType"

// MARK: GuideListView
static let expandedGuideItems = "expandedGuideItems"

// static func loadCustomIssues(jsonFileName: String) -> [CustomIssuesModel] {
// let lc: [CustomIssuesModel] = SMFile.loadBundleJSONFile(jsonFileName + ".json")
// return lc
Expand Down
181 changes: 102 additions & 79 deletions SwiftPamphletApp/Guide/View/GuideListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,94 +12,121 @@ import SMFile
struct GuideListView: View {
@Query(BookmarkModel.all) var bookmarks: [BookmarkModel]
@State private var apBookmarks: [String] = [String]()
@State var listModel = GuideListModel()
@State private var limit: Int = 50
@State private var trigger = false // 触发列表书签状态更新
@State var listModel: GuideListModel
@Binding var selectedItem: L? // 改为 L? 类型
@AppStorage(SPC.expandedGuideItems) private var expandedItemsString: String = ""
@State private var expandedItems: Set<String> = []

var body: some View {
if listModel.searchText.isEmpty == false {
HStack {
Text("搜索”\(listModel.searchText)“结果如下")
Button {
listModel.searchText = ""
} label: {
Image(systemName: "xmark.circle")
List(selection: $selectedItem) {
ForEach(listModel.filtered()) { item in
OutlineGroup(
item: item,
bookmarks: apBookmarks,
selectedItem: $selectedItem,
expandedItems: $expandedItems
)
}
}
.searchable(
text: $listModel.searchText,
prompt: "搜索 Apple 技术手册"
)
#if os(macOS)
.listStyle(.sidebar)
#endif
.onAppear {
// 读取保存的展开状态
expandedItems = Set(expandedItemsString.split(separator: ",").map(String.init))
print("Loaded expanded items: \(expandedItems.count)") // Debug
updateApBookmarks()
}
.onChange(of: expandedItems) { _, newValue in
// 保存展开状态
expandedItemsString = newValue.joined(separator: ",")
print("Saved expanded items: \(newValue.count)") // Debug
}
.overlay {
if listModel.filtered().isEmpty {
ContentUnavailableView {
Label("无结果", systemImage: "rectangle.and.text.magnifyingglass")
} description: {
Text("请再次输入")
}
}
.padding(.top, 10)
}
NavigationStack {
SPOutlineListView(d: listModel.filtered(), c: \.sub) { i in
NavigationLink(
destination: GuideDetailView(
t: i.t,
icon: i.icon,
plName: listModel.plName,
limit: $limit,
trigger: $trigger
)
}

private struct OutlineGroup: View {
let item: L
let bookmarks: [String]
@Binding var selectedItem: L?
@Binding var expandedItems: Set<String>

var body: some View {
if let subItems = item.sub {
DisclosureGroup(
isExpanded: expandedBinding(for: item.t, in: $expandedItems)
) {
HStack(spacing:3) {
if i.icon.isEmpty == false {
Image(systemName: i.icon)
.foregroundStyle(i.sub == nil ? Color.secondary : .indigo)
} else if i.sub != nil {
Image(systemName: "folder.fill")
.foregroundStyle(.indigo)
}
Text(listModel.searchText.isEmpty == true ? GuideListModel.simpleTitle(i.t) : i.t)
Spacer()
if apBookmarks.contains(i.t) {
Image(systemName: "bookmark")
.foregroundStyle(.secondary)
.font(.footnote)
}
ForEach(subItems) { subItem in
OutlineGroup(
item: subItem,
bookmarks: bookmarks,
selectedItem: $selectedItem,
expandedItems: $expandedItems
)
}
.contentShape(Rectangle())
} label: {
ItemRow(item: item, bookmarks: bookmarks)
.tag(item)
}
} else {
ItemRow(item: item, bookmarks: bookmarks)
.tag(item)
}
.searchable(
text: $listModel.searchText,
prompt: "搜索 Apple 技术手册"
)
#if os(macOS)
.listStyle(.sidebar)
#endif
.onChange(of: trigger, { oldValue, newValue in
updateApBookmarks()
})
.onAppear(perform: {
updateApBookmarks()
//导出内容
// listModel.buildMDContent()

})
.overlay {
if listModel.filtered().isEmpty {
ContentUnavailableView {
Label(
"无结果",
systemImage: "rectangle.and.text.magnifyingglass"
)
} description: {
Text("请再次输入")
}
}
}

private static func expandedBinding(for id: String, in expandedItems: Binding<Set<String>>) -> Binding<Bool> {
Binding(
get: { expandedItems.wrappedValue.contains(id) },
set: { isExpanded in
if isExpanded {
expandedItems.wrappedValue.insert(id)
} else {
expandedItems.wrappedValue.remove(id)
}
}
)
}

private struct ItemRow: View {
let item: L
let bookmarks: [String]

var body: some View {
HStack(spacing: 3) {
if !item.icon.isEmpty {
Image(systemName: item.icon)
.foregroundStyle(item.sub == nil ? Color.secondary : .indigo)
} else if item.sub != nil {
Image(systemName: "folder.fill")
.foregroundStyle(.indigo)
}
Text(GuideListModel.simpleTitle(item.t))
Spacer()
if bookmarks.contains(item.t) {
Image(systemName: "bookmark")
.foregroundStyle(.secondary)
.font(.footnote)
}
} // end overlay
}
.contentShape(Rectangle())
}
#if os(iOS)
.navigationTitle("Apple 开发手册")
#endif
}

func updateApBookmarks() {
apBookmarks = [String]()
for bm in bookmarks {
// if bm.pamphletName == "ap" {
// apBookmarks.append(bm.name)
// }
apBookmarks.append(bm.name)
}
apBookmarks = bookmarks.map(\.name)
}
}

Expand Down Expand Up @@ -183,15 +210,11 @@ final class GuideListModel {
} // end for one
SMFile.writeToDownload(fileName: "read.md", content: md)
}



}

struct L: Hashable, Identifiable {
var id = UUID()
var id: String { t }
var t: String
var icon: String = ""
var sub: [L]?
}

35 changes: 25 additions & 10 deletions SwiftPamphletApp/HomeUI/DataLink.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ struct DataLink: Identifiable {
selectDev:Binding<DeveloperModel?>,
selectInfoBindable: IOInfo?,
selectDevBindable: DeveloperModel?,
selectGuideItem: Binding<L?>,
selectGuideItemBindable: L?,
limit: Binding<Int>,
trigger: Binding<Bool>,
type: ShowType
) -> some View {
switch title {
Expand Down Expand Up @@ -92,17 +96,28 @@ struct DataLink: Identifiable {
case "Apple技术":
switch type {
case .content:
GuideListView(listModel: GuideListModel(plModel: AppleGuide().outline, pplName: "ap"))
GuideListView(
listModel: GuideListModel(plModel: AppleGuide().outline, pplName: "ap"),
selectedItem: selectGuideItem
)
case .detail:
IntroView()
}
case "计算机科学":
switch type {
case .content:
GuideListView(listModel: GuideListModel(plModel: CSGuide().outline, pplName: "cs"))
case .detail:
IntroView()
if let item = selectGuideItemBindable {
GuideDetailView(
t: item.t,
icon: item.icon,
plName: "ap",
limit: limit,
trigger: trigger
)
}
}
// case "计算机科学":
// switch type {
// case .content:
// GuideListView(listModel: GuideListModel(plModel: CSGuide().outline, pplName: "cs"))
// case .detail:
// IntroView()
// }
case "WWDC":
switch type {
case .content:
Expand All @@ -121,7 +136,7 @@ struct DataLink: Identifiable {
switch type {
case .content:
// 默认
GuideListView(listModel: GuideListModel(plModel: AppleGuide().outline, pplName: "ap"))
InfoListView(selectInfo: selectInfo)
case .detail:
IntroView()
}
Expand Down
38 changes: 29 additions & 9 deletions SwiftPamphletApp/HomeUI/HomeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ struct HomeView: View {

@AppStorage(SPC.isFirstRun) var isFirstRun = true
@Environment(\.scenePhase) var scenePhase
@State private var selectedGuideItem: L? = nil // 改为 L? 类型
@State private var limit: Int = 50 // 为 GuideDetailView 添加
@State private var trigger: Bool = false // 为 GuideDetailView 添加

var body: some View {
#if os(macOS)
Expand All @@ -33,6 +36,10 @@ struct HomeView: View {
selectDev: $selectDev,
selectInfoBindable: selectInfo,
selectDevBindable: selectDev,
selectGuideItem: $selectedGuideItem,
selectGuideItemBindable: selectedGuideItem,
limit: $limit,
trigger: $trigger,
type: .content
)
} else {
Expand All @@ -45,14 +52,28 @@ struct HomeView: View {
}
} detail: {
if !selectedDataLinkString.isEmpty {
DataLink.viewToShow(
for: selectedDataLinkString,
selectInfo: $selectInfo,
selectDev: $selectDev,
selectInfoBindable: selectInfo,
selectDevBindable: selectDev,
type: .detail
)
if selectedDataLinkString == "Apple技术", let item = selectedGuideItem {
GuideDetailView(
t: item.t,
icon: item.icon,
plName: "ap",
limit: $limit,
trigger: $trigger
)
} else {
DataLink.viewToShow(
for: selectedDataLinkString,
selectInfo: $selectInfo,
selectDev: $selectDev,
selectInfoBindable: selectInfo,
selectDevBindable: selectDev,
selectGuideItem: $selectedGuideItem,
selectGuideItemBindable: selectedGuideItem,
limit: $limit,
trigger: $trigger,
type: .detail
)
}
} else {
IntroView()
}
Expand Down Expand Up @@ -82,7 +103,6 @@ struct HomeView: View {
.onOpenURL(perform: { url in
// 处理外部链接
})

#endif
}
}
Expand Down

0 comments on commit f6a2e1e

Please sign in to comment.