Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions Flipcash/Core/Screens/Conversation/ConversationScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -534,8 +534,14 @@ struct ConversationScreen: View {
// which is why this reads `withholdsTranscript` and not `obscuresTranscript`: a chat
// whose rules haven't landed yet is blurred without yet refusing anything.
// Also stands in while an empty transcript's first load is out, so a chat with nothing
// cached opens on the placeholder and paints once with its history.
showsGatePlaceholder: (gate.withholdsTranscript || !didInitialRead) && (coordinator?.items.isEmpty ?? true),
// cached opens on the placeholder and paints once with its history, except under the
// group-ready card.
showsGatePlaceholder: GroupReadyCard.showsGatePlaceholder(
withholdsTranscript: gate.withholdsTranscript,
didInitialRead: didInitialRead,
transcriptIsEmpty: coordinator?.items.isEmpty ?? true,
cardShown: showsInviteCard
),
gateMintName: gateMintName,
gateShortfall: gateShortfall,
gateDisplayCurrency: ratesController.displayCurrency,
Expand Down
14 changes: 14 additions & 0 deletions Flipcash/Core/Screens/Conversation/GroupReadyCard.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@ enum GroupReadyCard {
)
}

/// Whether the transcript draws the gate's placeholder shapes behind an empty chat.
///
/// A gated chat the viewer is refused always gets them. Otherwise they only bridge an empty
/// transcript's first load, and not while the group-ready card shows: that chat is new and has
/// nothing to wait for, so the shapes would sit behind the card.
static func showsGatePlaceholder(
withholdsTranscript: Bool,
didInitialRead: Bool,
transcriptIsEmpty: Bool,
cardShown: Bool
) -> Bool {
(withholdsTranscript || (!didInitialRead && !cardShown)) && transcriptIsEmpty
}

/// The chat-list line for a conversation that has no message at all: an invitation while the
/// group-ready card would show, "Nothing yet" otherwise. Client-only, so it follows the card
/// leaving once someone joins.
Expand Down
17 changes: 17 additions & 0 deletions FlipcashTests/Chat/GroupReadyCardTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,21 @@ struct GroupReadyCardTests {
// A DM never gets the invitation.
#expect(GroupReadyCard.emptyPreview(for: chat(type: .contactDm, count: 1, canInvite: true, isPrivate: false)) == nothing)
}

@Test("Placeholder shapes: none under the card, kept for a gated chat and a plain first load")
func gatePlaceholder() {
func shows(withholds: Bool = false, read: Bool, empty: Bool = true, card: Bool) -> Bool {
GroupReadyCard.showsGatePlaceholder(withholdsTranscript: withholds, didInitialRead: read, transcriptIsEmpty: empty, cardShown: card)
}
// A new group before its first read: the card, no shapes.
#expect(!shows(read: false, card: true))
// An empty chat with no card still bridges its first load.
#expect(shows(read: false, card: false))
// A gated chat keeps them, card or not.
#expect(shows(withholds: true, read: true, card: false))
#expect(shows(withholds: true, read: false, card: true))
// Rows loaded, or read finished: none.
#expect(!shows(read: false, empty: false, card: false))
#expect(!shows(read: true, card: false))
}
}
Loading