mirror of
https://github.com/sudosylabs/vnidrop.git
synced 2026-08-05 10:29:58 +02:00
fix(apple): stop delete confirmation re-presenting on macOS
Confirming a transfer/history deletion flashed the same confirmation alert a second time before it went away. The destructive button runs confirmDelete synchronously (setting isDeleting = true), while the alert's isPresented dismiss binding fires asynchronously and then no-ops because its `if !isDeleting` guard is already false — leaving the open flag set, so macOS re-reads the binding as true and re-presents the alert until the async delete finally clears it. Close the confirmation flag synchronously in confirmDeleteTransfer / confirmHistoryDelete so there's no window for re-presentation. Tests assert the flag clears immediately, before the async delete completes.
This commit is contained in:
@@ -24,6 +24,9 @@ final class ReceiveModelTests: XCTestCase {
|
|||||||
XCTAssertEqual(model.state.historyDeleteTarget, .transfer(transferId: 5))
|
XCTAssertEqual(model.state.historyDeleteTarget, .transfer(transferId: 5))
|
||||||
|
|
||||||
model.confirmHistoryDelete()
|
model.confirmHistoryDelete()
|
||||||
|
// Must close immediately (not after the async delete) so the alert can't
|
||||||
|
// re-present on macOS.
|
||||||
|
XCTAssertNil(model.state.historyDeleteTarget)
|
||||||
await waitUntil { core.deletedTransfers.contains(5) }
|
await waitUntil { core.deletedTransfers.contains(5) }
|
||||||
XCTAssertEqual(core.deletedTransfers, [5])
|
XCTAssertEqual(core.deletedTransfers, [5])
|
||||||
XCTAssertNil(model.state.historyDeleteTarget)
|
XCTAssertNil(model.state.historyDeleteTarget)
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ final class SendModelTests: XCTestCase {
|
|||||||
XCTAssertTrue(model.state.isDeleteConfirmationOpen)
|
XCTAssertTrue(model.state.isDeleteConfirmationOpen)
|
||||||
|
|
||||||
model.confirmDeleteTransfer()
|
model.confirmDeleteTransfer()
|
||||||
|
// Must close immediately (not after the async delete) so the alert can't
|
||||||
|
// re-present on macOS.
|
||||||
|
XCTAssertFalse(model.state.isDeleteConfirmationOpen)
|
||||||
await waitUntil { core.deletedTransfers.contains(3) }
|
await waitUntil { core.deletedTransfers.contains(3) }
|
||||||
XCTAssertEqual(core.deletedTransfers, [3])
|
XCTAssertEqual(core.deletedTransfers, [3])
|
||||||
XCTAssertNil(model.state.selectedTransferId)
|
XCTAssertNil(model.state.selectedTransferId)
|
||||||
|
|||||||
@@ -121,6 +121,10 @@ final class ReceiveModel: ObservableObject {
|
|||||||
func confirmHistoryDelete() {
|
func confirmHistoryDelete() {
|
||||||
guard let target = state.historyDeleteTarget, !state.isDeletingHistory else { return }
|
guard let target = state.historyDeleteTarget, !state.isDeletingHistory else { return }
|
||||||
state.isDeletingHistory = true
|
state.isDeletingHistory = true
|
||||||
|
// Close synchronously: the alert's dismiss binding runs async and no-ops while
|
||||||
|
// `isDeletingHistory`, which would otherwise leave the target set and macOS
|
||||||
|
// re-present it.
|
||||||
|
state.historyDeleteTarget = nil
|
||||||
Task {
|
Task {
|
||||||
let result: Result<Void, Error>
|
let result: Result<Void, Error>
|
||||||
switch target {
|
switch target {
|
||||||
|
|||||||
@@ -207,6 +207,9 @@ final class SendModel: ObservableObject {
|
|||||||
func confirmDeleteTransfer() {
|
func confirmDeleteTransfer() {
|
||||||
guard let transferId = state.selectedTransferId, !state.isDeleting else { return }
|
guard let transferId = state.selectedTransferId, !state.isDeleting else { return }
|
||||||
state.isDeleting = true
|
state.isDeleting = true
|
||||||
|
// Close synchronously: the alert's dismiss binding runs async and no-ops while
|
||||||
|
// `isDeleting`, which would otherwise leave the flag true and macOS re-present it.
|
||||||
|
state.isDeleteConfirmationOpen = false
|
||||||
Task {
|
Task {
|
||||||
let result = await repository.delete(transferId: transferId)
|
let result = await repository.delete(transferId: transferId)
|
||||||
switch result {
|
switch result {
|
||||||
|
|||||||
Reference in New Issue
Block a user