mirror of
https://github.com/block/buzz.git
synced 2026-11-08 18:31:56 +00:00
fix(mobile): recover historical namesake chip identity
Signed-off-by: Logan Johnson <loganj@squareup.com>
This commit is contained in:
@@ -90,23 +90,25 @@ Map<String, Set<String>> renderedMentionBindings(
|
||||
key: key,
|
||||
));
|
||||
add(label, key);
|
||||
bindings.putIfAbsent(match.group(1)!.toLowerCase(), () => <String>{});
|
||||
}
|
||||
final winning = mentionOccurrences(
|
||||
content,
|
||||
bindings.keys,
|
||||
).map((range) => range.label).toSet();
|
||||
for (final entry in bindings.entries) {
|
||||
if (entry.value.length < 2) continue;
|
||||
entry.value.removeAll(
|
||||
qualified
|
||||
.where(
|
||||
(q) =>
|
||||
q.base == entry.key &&
|
||||
winning.contains(q.label) &&
|
||||
bindings[q.label]?.length == 1,
|
||||
)
|
||||
.map((q) => q.key),
|
||||
);
|
||||
final claimed = qualified.where((q) => winning.contains(q.label)).toList();
|
||||
final bases = claimed.map((q) => q.base).where(winning.contains).toSet();
|
||||
final remaining = keys.difference(claimed.map((q) => q.key).toSet());
|
||||
// Ordinary sibling mentions claim their own identities before recovering a
|
||||
// historical namesake. Current aliases must not retarget that namesake.
|
||||
for (final label in winning.difference(bases)) {
|
||||
final candidates = bindings[label]!;
|
||||
if (candidates.length == 1) remaining.removeAll(candidates);
|
||||
}
|
||||
for (final base in bases) {
|
||||
// Multiple historical labels or leftover tagged keys cannot be paired
|
||||
// deterministically. Leave them as non-clickable references, not guesses.
|
||||
bindings[base] = bases.length == 1 ? remaining.toSet() : <String>{};
|
||||
}
|
||||
return bindings;
|
||||
}
|
||||
|
||||
@@ -67,4 +67,46 @@ void main() {
|
||||
expect(tester.takeException(), isNull);
|
||||
semantics.dispose();
|
||||
});
|
||||
testWidgets('historical namesakes preserve targets with ordinary siblings', (
|
||||
tester,
|
||||
) async {
|
||||
final first = 'a' * 64, second = 'b' * 64, sibling = 'c' * 64;
|
||||
for (final firstName in ['Scout', 'Renamed Scout', first]) {
|
||||
for (final secondName in ['Scout', 'Renamed Scout', second]) {
|
||||
for (final reverse in [false, true]) {
|
||||
for (final ambiguous in [false, true]) {
|
||||
final entries = {
|
||||
first: firstName,
|
||||
second: secondName,
|
||||
sibling: 'Alice',
|
||||
if (ambiguous) 'd' * 64: 'Unknown',
|
||||
}.entries.toList();
|
||||
String? tapped;
|
||||
await tester.pumpWidget(
|
||||
WidgetHelpers.testable(
|
||||
child: MessageContent(
|
||||
content: '@Scout @Scout ($second) @Alice',
|
||||
mentionNames: Map.fromEntries(
|
||||
reverse ? entries.reversed : entries,
|
||||
),
|
||||
onMentionTap: (key) => tapped = key,
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
if (ambiguous) {
|
||||
expect(find.text(firstName), findsNothing);
|
||||
} else {
|
||||
await tester.tap(find.text(firstName));
|
||||
expect(tapped, first);
|
||||
}
|
||||
await tester.tap(find.text('Scout (bbbbbbbb…bbbb)'));
|
||||
expect(tapped, second);
|
||||
await tester.tap(find.text('Alice'));
|
||||
expect(tapped, sibling);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user