Implement batch delete functionality in HistoryView, allowing users to select multiple items for deletion; enhance UI with confirmation views and improved state management for better user experience.

main
v504 2 months ago
parent 37d8d72922
commit d40cb9eb99

@ -82,36 +82,6 @@
endingLineNumber = "243"
landmarkName = "HistoryView"
landmarkType = "14">
<Locations>
<Location
uuid = "79506791-23FD-416B-9053-8A0FE086814D - b2ff3d7d29aa52a4"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "closure #1 () -&gt; () in closure #1 (MyQrCode.HistoryView.HistoryFilter) -&gt; MyQrCode.FilterChip in closure #1 () -&gt; SwiftUI.ForEach&lt;Swift.Array&lt;MyQrCode.HistoryView.HistoryFilter&gt;, MyQrCode.HistoryView.HistoryFilter, MyQrCode.FilterChip&gt; in closure #1 () -&gt; &lt;&lt;opaque return type of SwiftUI.View.padding(SwiftUI.Edge.Set, Swift.Optional&lt;CoreGraphics.CGFloat&gt;) -&gt; some&gt;&gt;.0 in MyQrCode.HistoryView.filterBar.getter : some"
moduleName = "MyQrCode.debug.dylib"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/yc/xcodeProjects/MyQrCode/MyQrCode/Views/HistoryView.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "243"
endingLineNumber = "243">
</Location>
<Location
uuid = "79506791-23FD-416B-9053-8A0FE086814D - 64fc53eb1c4f7b39"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "MyQrCode.HistoryView.historyList.getter : some"
moduleName = "MyQrCode.debug.dylib"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/yc/xcodeProjects/MyQrCode/MyQrCode/Views/HistoryView.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "244"
endingLineNumber = "244">
</Location>
</Locations>
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>

@ -6,12 +6,14 @@ struct HistoryView: View {
@State private var searchText = ""
@State private var selectedFilter: HistoryFilter = .all
@State private var showingCreateSheet = false
@State private var showingClearAlert = false
@State private var itemToDelete: HistoryItem?
@State private var showingDeleteAlert = false
@State private var showingClearConfirmSheet = false
@State private var allHistoryItems: [HistoryItem] = []
@State private var isLoading = false
@State private var refreshTrigger = false
@State private var isBatchDeleteMode = false
@State private var selectedItemsForDelete: Set<UUID> = []
enum HistoryFilter: String, CaseIterable {
case all = "all"
@ -107,17 +109,51 @@ struct HistoryView: View {
.navigationTitle("历史记录")
.navigationBarTitleDisplayMode(.large)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
ToolbarItem(placement: .navigationBarTrailing) {
HStack(spacing: 16) {
if isBatchDeleteMode {
//
Button(action: {
// /
if selectedItemsForDelete.count == filteredItems.count {
selectedItemsForDelete.removeAll()
} else {
selectedItemsForDelete = Set(filteredItems.compactMap { $0.id })
}
}) {
Image(systemName: selectedItemsForDelete.count == filteredItems.count ? "checkmark.rectangle.fill" : "rectangle.on.rectangle")
.foregroundColor(.blue)
}
Button(action: {
if !selectedItemsForDelete.isEmpty {
deleteSelectedItems()
}
}) {
Image(systemName: "trash.fill")
.foregroundColor(.red)
}
.disabled(selectedItemsForDelete.isEmpty)
//
Button(action: {
exitBatchDeleteMode()
}) {
Image(systemName: "xmark.circle")
.foregroundColor(.gray)
}
} else {
//
//
if !allHistoryItems.isEmpty {
Button(action: {
showingClearAlert = true
enterBatchDeleteMode()
}) {
Image(systemName: "trash")
.foregroundColor(.red)
}
.disabled(coreDataManager.fetchHistoryItems().isEmpty)
}
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: {
showingCreateSheet = true
}) {
@ -125,16 +161,16 @@ struct HistoryView: View {
}
}
}
}
}
.sheet(isPresented: $showingCreateSheet) {
CreateCodeView()
}
.alert("清空历史记录", isPresented: $showingClearAlert) {
Button("取消", role: .cancel) { }
Button("清空", role: .destructive) {
clearHistory()
}
} message: {
Text("确定要清空所有历史记录吗?此操作不可撤销。")
.sheet(isPresented: $showingClearConfirmSheet) {
ClearHistoryConfirmView(
isPresented: $showingClearConfirmSheet,
onConfirm: clearHistory
)
}
.alert("删除确认", isPresented: $showingDeleteAlert) {
Button("取消", role: .cancel) { }
@ -205,6 +241,47 @@ struct HistoryView: View {
showingDeleteAlert = true
}
// MARK: -
private func enterBatchDeleteMode() {
isBatchDeleteMode = true
//
selectedItemsForDelete = Set(filteredItems.compactMap { $0.id })
}
private func exitBatchDeleteMode() {
isBatchDeleteMode = false
selectedItemsForDelete.removeAll()
}
private func deleteSelectedItems() {
//
let itemsToDelete = allHistoryItems.filter { item in
guard let id = item.id else { return false }
return selectedItemsForDelete.contains(id)
}
//
for item in itemsToDelete {
coreDataManager.deleteHistoryItem(item)
}
//
allHistoryItems.removeAll { item in
guard let id = item.id else { return false }
return selectedItemsForDelete.contains(id)
}
// 退
selectedItemsForDelete.removeAll()
isBatchDeleteMode = false
//
DispatchQueue.main.async {
allHistoryItems = coreDataManager.fetchHistoryItems()
refreshTrigger.toggle()
}
}
// MARK: -
private var searchBar: some View {
HStack {
@ -265,6 +342,17 @@ struct HistoryView: View {
},
onDelete: {
showDeleteConfirmation(for: item)
},
isBatchDeleteMode: isBatchDeleteMode,
isSelected: selectedItemsForDelete.contains(item.id ?? UUID()),
onToggleSelection: {
if let id = item.id {
if selectedItemsForDelete.contains(id) {
selectedItemsForDelete.remove(id)
} else {
selectedItemsForDelete.insert(id)
}
}
}
)
}
@ -372,9 +460,22 @@ struct HistoryItemRow: View {
let item: HistoryItem
let onToggleFavorite: () -> Void
let onDelete: () -> Void
let isBatchDeleteMode: Bool
let isSelected: Bool
let onToggleSelection: () -> Void
var body: some View {
HStack(spacing: 12) {
//
if isBatchDeleteMode {
Button(action: onToggleSelection) {
Image(systemName: isSelected ? "checkmark.square.fill" : "square")
.font(.system(size: 20))
.foregroundColor(isSelected ? .blue : .gray)
}
.buttonStyle(PlainButtonStyle())
}
//
VStack {
if let dataTypeString = item.dataType,
@ -496,3 +597,75 @@ struct HistoryItemRow: View {
return formatter.string(from: date)
}
}
// MARK: -
struct ClearHistoryConfirmView: View {
@Binding var isPresented: Bool
let onConfirm: () -> Void
var body: some View {
NavigationView {
VStack(spacing: 20) {
//
Image(systemName: "exclamationmark.triangle.fill")
.font(.system(size: 50))
.foregroundColor(.red)
//
Text("清空历史记录")
.font(.title2)
.fontWeight(.bold)
//
Text("此操作将删除所有历史记录,且不可撤销")
.font(.body)
.foregroundColor(.secondary)
.multilineTextAlignment(.center)
Spacer()
//
VStack(spacing: 12) {
//
Button(action: {
onConfirm()
isPresented = false
}) {
HStack {
Image(systemName: "trash.fill")
Text("确认删除")
}
.frame(maxWidth: .infinity)
.padding()
.background(Color.red)
.foregroundColor(.white)
.cornerRadius(10)
}
//
Button(action: {
isPresented = false
}) {
Text("取消")
.frame(maxWidth: .infinity)
.padding()
.background(Color(.systemGray5))
.foregroundColor(.primary)
.cornerRadius(10)
}
}
}
.padding(20)
.navigationTitle("确认删除")
.navigationBarTitleDisplayMode(.inline)
.navigationBarBackButtonHidden(true)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button("关闭") {
isPresented = false
}
}
}
}
}
}
Loading…
Cancel
Save