mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-08-29 07:27:16 +00:00
fix: gate in-sheet actions on launch presentation; require isFavorite for DM restore
Addresses two Codex P2 review comments on #1364: - ContentSheetViews fingerprint drill-down and image-picker gates missed the launch-presentation flag, so on the launch-fallback path (only presentsConversationListOnLaunch true) tapping a peer fingerprint was a silent no-op. Add || appChromeModel.presentsConversationListOnLaunch to both in-sheet gate conditions to match the ContentView call site. - isDirectChatRestorable treated any non-nil favorite record as restorable, but removeFavorite retains a record (isFavorite: false, theyFavoritedUs: true) when the peer still favorites us, so a DM to an unfavorited peer reopened on restart. Key the resolver on isFavorite, not record existence. Adds a regression test for the unfavorited-but-still-favorited-by-them peer.
This commit is contained in:
parent
5a890559c1
commit
c01be3b359
@ -185,7 +185,7 @@ final class AppRuntime: ObservableObject {
|
||||
favorites: FavoritesPersistenceService
|
||||
) -> Bool {
|
||||
isDirectChatRestorable(peerID, isPeerFavorited: {
|
||||
favorites.getFavoriteStatus(forPeerID: $0.toShort()) != nil
|
||||
favorites.getFavoriteStatus(forPeerID: $0.toShort())?.isFavorite ?? false
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -85,7 +85,7 @@ struct ContentPeopleSheetView: View {
|
||||
}
|
||||
}
|
||||
.navigationDestination(isPresented: Binding(
|
||||
get: { appChromeModel.showingFingerprintFor != nil && (showSidebar || privateConversationModel.selectedPeerID != nil) },
|
||||
get: { appChromeModel.showingFingerprintFor != nil && (showSidebar || privateConversationModel.selectedPeerID != nil || appChromeModel.presentsConversationListOnLaunch) },
|
||||
set: { isPresented in
|
||||
if !isPresented {
|
||||
appChromeModel.clearFingerprint()
|
||||
@ -105,7 +105,7 @@ struct ContentPeopleSheetView: View {
|
||||
#endif
|
||||
#if os(iOS)
|
||||
.fullScreenCover(isPresented: Binding(
|
||||
get: { showImagePicker && (showSidebar || privateConversationModel.selectedPeerID != nil) },
|
||||
get: { showImagePicker && (showSidebar || privateConversationModel.selectedPeerID != nil || appChromeModel.presentsConversationListOnLaunch) },
|
||||
set: { newValue in
|
||||
if !newValue {
|
||||
showImagePicker = false
|
||||
|
||||
@ -183,6 +183,27 @@ final class ConversationStoreLastActiveTests: XCTestCase {
|
||||
)
|
||||
}
|
||||
|
||||
func test_production_unfavoritedPeerWhoStillFavoritesUsIsNotRestorable() {
|
||||
// removeFavorite RETAINS a record (isFavorite: false, theyFavoritedUs:
|
||||
// true) when the peer still favorites us. The resolver must key on
|
||||
// isFavorite, not mere record existence — otherwise a DM to a peer we
|
||||
// deliberately unfavorited reopens on restart, contradicting the
|
||||
// "is a persisted favorite" contract. Regression for Codex P2 review.
|
||||
let favorites = FavoritesPersistenceService(keychain: MockKeychain())
|
||||
let noiseKey = Data((0..<32).map(UInt8.init))
|
||||
favorites.addFavorite(peerNoisePublicKey: noiseKey, peerNickname: "Alice")
|
||||
favorites.updatePeerFavoritedUs(peerNoisePublicKey: noiseKey, favorited: true)
|
||||
favorites.removeFavorite(peerNoisePublicKey: noiseKey)
|
||||
|
||||
let fullHexPeer = PeerID(str: noiseKey.hexEncodedString())
|
||||
// The record survives (they still favorite us) but isFavorite is false.
|
||||
XCTAssertNotNil(favorites.getFavoriteStatus(forPeerID: fullHexPeer.toShort()))
|
||||
XCTAssertFalse(favorites.getFavoriteStatus(forPeerID: fullHexPeer.toShort())!.isFavorite)
|
||||
XCTAssertFalse(
|
||||
AppRuntime.isDirectChatRestorable(fullHexPeer, favorites: favorites)
|
||||
)
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
private func makeStorage() -> UserDefaults {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user