Skip to content

Commit f296012

Browse files
authored
fix: if example message contains multiple of the same lemma, bold each of them instead of showing as seperate messages (#1795)
1 parent 918c319 commit f296012

File tree

1 file changed

+71
-38
lines changed

1 file changed

+71
-38
lines changed

lib/pangea/analytics_details_popup/lemma_use_example_messages.dart

+71-38
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart';
1010
import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart';
1111
import 'package:fluffychat/pangea/analytics_misc/learning_skills_enum.dart';
1212
import 'package:fluffychat/pangea/events/event_wrappers/pangea_message_event.dart';
13+
import 'package:fluffychat/pangea/events/models/pangea_token_model.dart';
1314
import 'package:fluffychat/widgets/matrix.dart';
1415

1516
class LemmaUseExampleMessages extends StatelessWidget {
@@ -21,14 +22,15 @@ class LemmaUseExampleMessages extends StatelessWidget {
2122
});
2223

2324
Future<List<ExampleMessage>> _getExampleMessages() async {
24-
final Set<ExampleMessage> examples = {};
25+
final List<ExampleMessage> examples = [];
2526
for (final OneConstructUse use in construct.uses) {
2627
if (use.useType.skillsEnumType != LearningSkillsEnum.writing ||
2728
use.metadata.eventId == null ||
2829
use.form == null ||
2930
use.pointValue <= 0) {
3031
continue;
3132
}
33+
3234
final Room? room = MatrixState.pangeaController.matrixState.client
3335
.getRoomById(use.metadata.roomId);
3436
if (room == null) continue;
@@ -38,7 +40,14 @@ class LemmaUseExampleMessages extends StatelessWidget {
3840
timeline = await room.getTimeline();
3941
}
4042

41-
final Event? event = await room.getEventById(use.metadata.eventId!);
43+
final exampleIndex = examples.indexWhere(
44+
(example) => example.event.eventId == use.metadata.eventId!,
45+
);
46+
47+
final Event? event = exampleIndex != -1
48+
? examples[exampleIndex].event
49+
: await room.getEventById(use.metadata.eventId!);
50+
4251
if (event == null) continue;
4352
final PangeaMessageEvent pangeaMessageEvent = PangeaMessageEvent(
4453
event: event,
@@ -48,18 +57,24 @@ class LemmaUseExampleMessages extends StatelessWidget {
4857
);
4958
final tokens = pangeaMessageEvent.messageDisplayRepresentation?.tokens;
5059
if (tokens == null || tokens.isEmpty) continue;
51-
final token =
52-
tokens.firstWhereOrNull((token) => token.text.content == use.form);
60+
final token = tokens.firstWhereOrNull(
61+
(token) => token.text.content == use.form,
62+
);
5363
if (token == null) continue;
5464

55-
final int offset = token.text.offset;
56-
examples.add(
57-
ExampleMessage(
58-
message: pangeaMessageEvent.messageDisplayText,
59-
offset: offset,
60-
length: use.form!.length,
61-
),
62-
);
65+
final example = exampleIndex == -1
66+
? ExampleMessage(
67+
event: event,
68+
message: pangeaMessageEvent.messageDisplayText,
69+
)
70+
: examples[exampleIndex];
71+
72+
if (example.isTokenAdded(token)) continue;
73+
example.addTokenPosition(token.text.offset, token.text.length);
74+
75+
exampleIndex == -1
76+
? examples.add(example)
77+
: examples[exampleIndex] = example;
6378
if (examples.length > 4) break;
6479
}
6580

@@ -77,7 +92,7 @@ class LemmaUseExampleMessages extends StatelessWidget {
7792
child: Column(
7893
crossAxisAlignment: CrossAxisAlignment.start,
7994
mainAxisAlignment: MainAxisAlignment.start,
80-
children: snapshot.data!.map((e) {
95+
children: snapshot.data!.map((example) {
8196
return Container(
8297
decoration: BoxDecoration(
8398
color: construct.lemmaCategory.color,
@@ -95,17 +110,7 @@ class LemmaUseExampleMessages extends StatelessWidget {
95110
fontSize: AppConfig.fontSizeFactor *
96111
AppConfig.messageFontSize,
97112
),
98-
children: [
99-
TextSpan(text: e.message.substring(0, e.offset)),
100-
TextSpan(
101-
text: e.message
102-
.substring(e.offset, e.offset + e.length),
103-
style: const TextStyle(fontWeight: FontWeight.bold),
104-
),
105-
TextSpan(
106-
text: e.message.substring(e.offset + e.length),
107-
),
108-
],
113+
children: example.textSpans,
109114
),
110115
),
111116
);
@@ -128,26 +133,54 @@ class LemmaUseExampleMessages extends StatelessWidget {
128133
}
129134

130135
class ExampleMessage {
136+
final Event event;
131137
final String message;
132-
final int offset;
133-
final int length;
138+
final Map<int, int> _tokenPositions;
134139

135140
ExampleMessage({
141+
required this.event,
136142
required this.message,
137-
required this.offset,
138-
required this.length,
139-
});
143+
}) : _tokenPositions = {};
140144

141-
@override
142-
bool operator ==(Object other) {
143-
if (identical(this, other)) return true;
145+
void addTokenPosition(int offset, int length) {
146+
_tokenPositions[offset] = length;
147+
}
144148

145-
return other is ExampleMessage &&
146-
other.message == message &&
147-
other.offset == offset &&
148-
other.length == length;
149+
bool isTokenAdded(PangeaToken token) {
150+
return _tokenPositions.keys.any(
151+
(offset) => offset == token.text.offset,
152+
);
149153
}
150154

151-
@override
152-
int get hashCode => message.hashCode ^ offset.hashCode ^ length.hashCode;
155+
List<List<int>> get _sortedTokenPositions {
156+
return _tokenPositions.entries
157+
.sorted((a, b) => a.key.compareTo(b.key))
158+
.map((entry) => [entry.key, entry.value])
159+
.toList();
160+
}
161+
162+
List<TextSpan> get textSpans {
163+
final spans = <TextSpan>[];
164+
int lastOffset = 0;
165+
for (final token in _sortedTokenPositions) {
166+
spans.add(
167+
TextSpan(
168+
text: message.substring(lastOffset, token[0]),
169+
),
170+
);
171+
spans.add(
172+
TextSpan(
173+
text: message.substring(token[0], token[0] + token[1]),
174+
style: const TextStyle(fontWeight: FontWeight.bold),
175+
),
176+
);
177+
lastOffset = token[0] + token[1];
178+
}
179+
spans.add(
180+
TextSpan(
181+
text: message.substring(lastOffset),
182+
),
183+
);
184+
return spans;
185+
}
153186
}

0 commit comments

Comments
 (0)