From 785c6fb45fcb7771c4e1379ecc8bbe5c923f1358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=88=B4=E9=93=AD?= Date: Sat, 13 Apr 2024 15:06:22 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=87=AA=E5=AE=9A=E6=A3=80?= =?UTF-8?q?=E7=B4=A2=E8=A7=86=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../App/SwiftPamphletAppConfig.swift | 7 ++ SwiftPamphletApp/HomeUI/HomeView.swift | 4 +- .../Category/EditCustomSearchView.swift | 2 +- .../InfoOrganizer/Info/EditInfoView.swift | 83 ++++++++++++++++++- .../InfoOrganizer/Info/InfoListView.swift | 59 +++++++++---- SwiftPamphletApp/Setting/SettingView.swift | 2 +- 6 files changed, 134 insertions(+), 23 deletions(-) diff --git a/SwiftPamphletApp/App/SwiftPamphletAppConfig.swift b/SwiftPamphletApp/App/SwiftPamphletAppConfig.swift index e991f080b..d2e426ad5 100644 --- a/SwiftPamphletApp/App/SwiftPamphletAppConfig.swift +++ b/SwiftPamphletApp/App/SwiftPamphletAppConfig.swift @@ -17,6 +17,13 @@ struct SPC { static let detailMinWidth: CGFloat = 550 static let githubHost = "https://github.com/" + + // MARK: AppStorage + static let selectedDataLinkString = "selectedDataLinkString" + static let isFirstRun = "isFirstRun" + static let customSearchTerm = "customSearchTerm" + static let isShowInspector = "isShowInspector" + static let inspectorType = "inspectorType" static func loadCustomIssues(jsonFileName: String) -> [CustomIssuesModel] { let lc: [CustomIssuesModel] = loadBundleJSONFile(jsonFileName + ".json") diff --git a/SwiftPamphletApp/HomeUI/HomeView.swift b/SwiftPamphletApp/HomeUI/HomeView.swift index d353e6a67..683aed78a 100644 --- a/SwiftPamphletApp/HomeUI/HomeView.swift +++ b/SwiftPamphletApp/HomeUI/HomeView.swift @@ -11,9 +11,9 @@ struct HomeView: View { @State private var selectedDataLinkString: String = "" @State private var selectInfo: IOInfo? = nil @State private var selectDev: DeveloperModel? = nil - @AppStorage("selectedDataLinkString") var sdLinkStr: String = "" + @AppStorage(SPC.selectedDataLinkString) var sdLinkStr: String = "" - @AppStorage("isFirstRun") var isFirstRun = true + @AppStorage(SPC.isFirstRun) var isFirstRun = true @Environment(\.scenePhase) var scenePhase var body: some View { diff --git a/SwiftPamphletApp/InfoOrganizer/Category/EditCustomSearchView.swift b/SwiftPamphletApp/InfoOrganizer/Category/EditCustomSearchView.swift index 54aef5c3e..826f995d5 100644 --- a/SwiftPamphletApp/InfoOrganizer/Category/EditCustomSearchView.swift +++ b/SwiftPamphletApp/InfoOrganizer/Category/EditCustomSearchView.swift @@ -8,7 +8,7 @@ import SwiftUI struct EditCustomSearchView: View { - @AppStorage("customSearchTerm") var term = "" + @AppStorage(SPC.customSearchTerm) var term = "" var body: some View { VStack { diff --git a/SwiftPamphletApp/InfoOrganizer/Info/EditInfoView.swift b/SwiftPamphletApp/InfoOrganizer/Info/EditInfoView.swift index 275242d40..45659bd19 100644 --- a/SwiftPamphletApp/InfoOrganizer/Info/EditInfoView.swift +++ b/SwiftPamphletApp/InfoOrganizer/Info/EditInfoView.swift @@ -17,12 +17,16 @@ struct EditInfoView: View { @Query(IOCategory.all) var categories: [IOCategory] + @State private var showSheet = false + // Inspector @State var isShowInspector = false enum InspectorType { case category, customSearch } @State var inspectorType: InspectorType = .category + @AppStorage(SPC.isShowInspector) var asIsShowInspector: Bool = false + @AppStorage(SPC.inspectorType) var asInspectorType: Int = 0 // Tab @State var selectedTab = 1 @@ -30,7 +34,7 @@ struct EditInfoView: View { @State var isStopLoadingWeb = false // webarchive @State var savingDataTrigger = false - + // 图集 @State var selectedPhotos = [PhotosPickerItem]() @State var addWebImageUrl = "" @@ -119,8 +123,35 @@ struct EditInfoView: View { info.category?.updateDate = Date.now }) Button("管理分类", action: manageCate) + Button("自定检索") { + showSheet = true + } + .help("command + s") + .sheet(isPresented: $showSheet, content: { + ScrollView(.vertical) { + ForEach(parseSearchTerms(), id: \.self) { term in + HStack { + ForEach(term, id: \.self) { oneTerm in + if oneTerm.description.hasPrefix("《") { + Text(oneTerm) + .bold() + } else { + Button(oneTerm) { + showSheet = false + info.des = oneTerm + "\n" + info.des + } + } + } + Spacer() + } + .padding(.leading, 1) + } + } + .padding(20) + }) + .keyboardShortcut(KeyEquivalent("s"), modifiers: .command) + Button("管理自定检索", action: manageCustomSearch) - } } // MARK: Tab 切换 @@ -277,10 +308,58 @@ struct EditInfoView: View { isShowInspector.toggle() } } + .onAppear(perform: { + _ = parseSearchTerms() + // AppStorage + if asInspectorType == 0 { + inspectorType = .category + } else if asInspectorType == 1 { + inspectorType = .customSearch + } + isShowInspector = asIsShowInspector + }) + .onChange(of: term) { oldValue, newValue in + _ = parseSearchTerms() + } + .onChange(of: isShowInspector) { oldValue, newValue in + asIsShowInspector = newValue + } + .onChange(of: inspectorType) { oldValue, newValue in + if newValue == InspectorType.category { + asInspectorType = 0 + } else if newValue == InspectorType.customSearch { + asInspectorType = 1 + } + } Spacer() } // end VStack } + // MARK: 自定检索 + @AppStorage(SPC.customSearchTerm) var term = "" + @State private var searchTerms: [[String]] = [[String]]() + func parseSearchTerms() -> [[String]] { + let terms = term.trimmingCharacters(in: .whitespacesAndNewlines).split(separator: "\n") + var sterms = [[String]]() + for t in terms { + if t.isEmpty == false { + let tWithoutWhitespaces = t.trimmingCharacters(in: .whitespaces) + if tWithoutWhitespaces.hasPrefix("//") { continue } + let ts = t.trimmingCharacters(in: .whitespaces).split(separator: ",") + var lineTs = [String]() + if ts.count > 1 { + for oneT in ts { + lineTs.append(String(oneT.trimmingCharacters(in: .whitespaces))) + } + } else { + lineTs.append(String(tWithoutWhitespaces)) + } + sterms.append(lineTs) + } // end if + } // end for + searchTerms = sterms + return sterms + } // MARK: 数据管理 func tabSwitch() { diff --git a/SwiftPamphletApp/InfoOrganizer/Info/InfoListView.swift b/SwiftPamphletApp/InfoOrganizer/Info/InfoListView.swift index 68466610f..45f0297af 100644 --- a/SwiftPamphletApp/InfoOrganizer/Info/InfoListView.swift +++ b/SwiftPamphletApp/InfoOrganizer/Info/InfoListView.swift @@ -19,13 +19,16 @@ struct InfoListView: View { @State var limit: Int = 50 @State var filterStar: Bool = false + @State private var showSheet = false + var body: some View { InfosView(filterCateName: filterCate, searchString: searchText, filterStar: filterStar, selectInfo: $selectInfo, sortOrder: sortOrder, limit: $limit) .navigationTitle("资料列表") .toolbar { ToolbarItem(placement: .navigation) { Button("添加资料", systemImage: "plus", action: addInfo) - .keyboardShortcut(KeyEquivalent("i"), modifiers: .command) + .help("command + =") + .keyboardShortcut(KeyEquivalent("="), modifiers: .command) } ToolbarItem(placement: .navigation) { Picker("分类", selection: $filterCate) { @@ -88,10 +91,10 @@ struct InfoListView: View { } .searchable(text: $searchText) .onAppear { - parseSearchTerms() + _ = parseSearchTerms() } .onChange(of: term) { oldValue, newValue in - parseSearchTerms() + _ = parseSearchTerms() } } @@ -99,36 +102,58 @@ struct InfoListView: View { // MARK: 自定义搜索 @ViewBuilder func customSearchView() -> some View { - Picker("自定检索", selection: $searchText) { - Text("自定检索") - .tag("") - Divider() - ForEach(searchTerms, id: \.self) { term in - Text(customSearchLabel(term)) - .tag(term) + Button(action: { + showSheet = true + }, label: { + Image(systemName: "mail.and.text.magnifyingglass") + }) + .sheet(isPresented: $showSheet, content: { + ScrollView(.vertical) { + ForEach(parseSearchTerms(), id: \.self) { term in + HStack { + ForEach(term, id: \.self) { oneTerm in + if oneTerm.description.hasPrefix("《") { + Text(oneTerm) + .bold() + } else { + Button(oneTerm) { + showSheet = false + searchText = oneTerm + } + } + } + Spacer() + } + .padding(.leading, 1) + } } - } + .padding(20) + }) } - @AppStorage("customSearchTerm") var term = "" - @State private var searchTerms: [String] = [String]() - func parseSearchTerms() { + @AppStorage(SPC.customSearchTerm) var term = "" + @State private var searchTerms: [[String]] = [[String]]() + func parseSearchTerms() -> [[String]] { let terms = term.trimmingCharacters(in: .whitespacesAndNewlines).split(separator: "\n") - searchTerms = [String]() + var sterms = [[String]]() for t in terms { if t.isEmpty == false { let tWithoutWhitespaces = t.trimmingCharacters(in: .whitespaces) if tWithoutWhitespaces.hasPrefix("//") { continue } let ts = t.trimmingCharacters(in: .whitespaces).split(separator: ",") + var lineTs = [String]() if ts.count > 1 { for oneT in ts { - searchTerms.append(String(oneT.trimmingCharacters(in: .whitespaces))) + lineTs.append(String(oneT.trimmingCharacters(in: .whitespaces))) } } else { - searchTerms.append(String(tWithoutWhitespaces)) + lineTs.append(String(tWithoutWhitespaces)) } + sterms.append(lineTs) } // end if } // end for + searchTerms = sterms + return sterms } func customSearchLabel(_ string: String) -> String { let strs = string.split(separator: "/") diff --git a/SwiftPamphletApp/Setting/SettingView.swift b/SwiftPamphletApp/Setting/SettingView.swift index ec44886bc..60976cc8d 100644 --- a/SwiftPamphletApp/Setting/SettingView.swift +++ b/SwiftPamphletApp/Setting/SettingView.swift @@ -25,7 +25,7 @@ struct SettingView: View { } // MARK: custom search - @AppStorage("customSearchTerm") var term = "" + @AppStorage(SPC.customSearchTerm) var term = "" @ViewBuilder func customSearch() -> some View { VStack {