diff --git a/Blackjack/Blackjack/Engine/GameState.swift b/Blackjack/Blackjack/Engine/GameState.swift index 42bece2..d947347 100644 --- a/Blackjack/Blackjack/Engine/GameState.swift +++ b/Blackjack/Blackjack/Engine/GameState.swift @@ -1204,6 +1204,20 @@ final class GameState: SessionManagedGame { allSessions.aggregatedBlackjackStats() } + // MARK: - Session History Management + + /// Deletes a session from history by ID. + func deleteSession(id: UUID) { + sessionHistory.removeAll { $0.id == id } + saveGameData() + } + + /// Deletes all session history. + func deleteAllSessionHistory() { + sessionHistory.removeAll() + saveGameData() + } + // MARK: - Game Reset /// Resets the entire game (keeps statistics). diff --git a/Blackjack/Blackjack/Resources/Localizable.xcstrings b/Blackjack/Blackjack/Resources/Localizable.xcstrings index b0a517b..347176d 100644 --- a/Blackjack/Blackjack/Resources/Localizable.xcstrings +++ b/Blackjack/Blackjack/Resources/Localizable.xcstrings @@ -2659,6 +2659,16 @@ } } } + }, + "Delete" : { + "comment" : "A button label that deletes a session.", + "isCommentAutoGenerated" : true + }, + "Delete Session" : { + + }, + "Delete Session?" : { + }, "DISPLAY" : { "localizations" : { @@ -6815,6 +6825,9 @@ } } } + }, + "This will permanently remove this session from your history." : { + }, "Three of a Kind" : { "comment" : "Description of a 21+3 side bet outcome when they have three of a kind.", diff --git a/Blackjack/Blackjack/Views/Sheets/StatisticsSheetView.swift b/Blackjack/Blackjack/Views/Sheets/StatisticsSheetView.swift index 0a87fdd..edec5f4 100644 --- a/Blackjack/Blackjack/Views/Sheets/StatisticsSheetView.swift +++ b/Blackjack/Blackjack/Views/Sheets/StatisticsSheetView.swift @@ -52,7 +52,14 @@ struct StatisticsSheetView: View { } } .sheet(item: $selectedSession) { session in - SessionDetailView(session: session, styleDisplayName: styleDisplayName(for: session.gameStyle)) + SessionDetailView( + session: session, + styleDisplayName: styleDisplayName(for: session.gameStyle), + onDelete: { + state.deleteSession(id: session.id) + selectedSession = nil + } + ) } } @@ -248,7 +255,7 @@ struct StatisticsSheetView: View { .buttonStyle(.plain) } - // Historical sessions - tap to view details + // Historical sessions - tap to view details, swipe to delete ForEach(state.sessionHistory) { session in Button { selectedSession = session @@ -270,6 +277,15 @@ struct StatisticsSheetView: View { } } .buttonStyle(.plain) + .swipeActions(edge: .trailing, allowsFullSwipe: true) { + Button(role: .destructive) { + withAnimation { + state.deleteSession(id: session.id) + } + } label: { + Label(String(localized: "Delete"), systemImage: "trash") + } + } } } .padding(.horizontal) @@ -528,8 +544,10 @@ private struct ChipStatRow: View { private struct SessionDetailView: View { let session: BlackjackSession let styleDisplayName: String + let onDelete: () -> Void @Environment(\.dismiss) private var dismiss + @State private var showDeleteConfirmation = false var body: some View { SheetContainerView( @@ -641,11 +659,44 @@ private struct SessionDetailView: View { .font(.system(size: Design.BaseFontSize.body)) .foregroundStyle(.white.opacity(Design.Opacity.strong)) } + + // Delete button + Button(role: .destructive) { + showDeleteConfirmation = true + } label: { + HStack { + Image(systemName: "trash") + Text(String(localized: "Delete Session")) + } + .font(.system(size: Design.BaseFontSize.body, weight: .medium)) + .frame(maxWidth: .infinity) + .padding(Design.Spacing.medium) + .background( + RoundedRectangle(cornerRadius: Design.CornerRadius.medium) + .fill(Color.red.opacity(Design.Opacity.hint)) + ) + .foregroundStyle(.red) + } + .padding(.horizontal) + .padding(.top, Design.Spacing.large) }, onCancel: nil, onDone: { dismiss() }, doneButtonText: String(localized: "Done") ) + .confirmationDialog( + String(localized: "Delete Session?"), + isPresented: $showDeleteConfirmation, + titleVisibility: .visible + ) { + Button(String(localized: "Delete"), role: .destructive) { + onDelete() + dismiss() + } + Button(String(localized: "Cancel"), role: .cancel) {} + } message: { + Text(String(localized: "This will permanently remove this session from your history.")) + } } private var sessionHeader: some View {