2409 automatically apply accentpunctuation corrections (#2449)
* feat: automatically accept normalization error matches * chore: on text change, if assistance state changes, update the IGC button
This commit is contained in:
parent
0dc3f13d99
commit
278219b163
5 changed files with 56 additions and 15 deletions
|
|
@ -59,6 +59,7 @@ class Choreographer {
|
|||
final StreamController stateStream = StreamController.broadcast();
|
||||
StreamSubscription? _trialStream;
|
||||
StreamSubscription? _languageStream;
|
||||
late AssistanceState _currentAssistanceState;
|
||||
|
||||
Choreographer(this.pangeaController, this.chatController) {
|
||||
_initialize();
|
||||
|
|
@ -86,6 +87,7 @@ class Choreographer {
|
|||
// for changes like enabling autocorrect
|
||||
setState();
|
||||
});
|
||||
_currentAssistanceState = assistanceState;
|
||||
clear();
|
||||
}
|
||||
|
||||
|
|
@ -248,6 +250,12 @@ class Choreographer {
|
|||
|
||||
/// Handles any changes to the text input
|
||||
_onChangeListener() {
|
||||
// Rebuild the IGC button if the state has changed.
|
||||
// This accounts for user typing after initial IGC has completed
|
||||
if (_currentAssistanceState != assistanceState) {
|
||||
setState();
|
||||
}
|
||||
|
||||
if (_noChange) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -453,6 +461,33 @@ class Choreographer {
|
|||
}
|
||||
}
|
||||
|
||||
void acceptNormalizationMatches() {
|
||||
for (int i = 0; i < igc.igcTextData!.matches.length; i++) {
|
||||
final isNormalizationError =
|
||||
igc.spanDataController.isNormalizationError(i);
|
||||
|
||||
if (!isNormalizationError) continue;
|
||||
final match = igc.igcTextData!.matches[i];
|
||||
|
||||
choreoRecord.addRecord(
|
||||
_textController.text,
|
||||
match: match.copyWith..status = PangeaMatchStatus.automatic,
|
||||
);
|
||||
|
||||
igc.igcTextData!.acceptReplacement(
|
||||
i,
|
||||
match.match.choices!.indexWhere(
|
||||
(c) => c.isBestCorrection,
|
||||
),
|
||||
);
|
||||
|
||||
_textController.setSystemText(
|
||||
igc.igcTextData!.originalInput,
|
||||
EditType.igc,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void onIgnoreMatch({required int cursorOffset}) {
|
||||
try {
|
||||
if (igc.igcTextData == null) {
|
||||
|
|
@ -635,6 +670,7 @@ class Choreographer {
|
|||
if (!stateStream.isClosed) {
|
||||
stateStream.add(0);
|
||||
}
|
||||
_currentAssistanceState = assistanceState;
|
||||
}
|
||||
|
||||
LayerLinkAndKey get itBarLinkAndKey =>
|
||||
|
|
|
|||
|
|
@ -172,6 +172,7 @@ class IgcController {
|
|||
}
|
||||
|
||||
igcTextData!.matches = confirmedMatches;
|
||||
choreographer.acceptNormalizationMatches();
|
||||
|
||||
// TODO - for each new match,
|
||||
// check if existing igcTextData has one and only one match with the same error text and correction
|
||||
|
|
|
|||
|
|
@ -4,11 +4,10 @@ import 'package:flutter/foundation.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/choreographer/models/choreo_record.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/models/language_detection_model.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/models/pangea_match_model.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/models/span_card_model.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/models/span_data.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/repo/language_detection_repo.dart';
|
||||
import 'package:fluffychat/pangea/common/constants/model_keys.dart';
|
||||
|
|
@ -363,13 +362,15 @@ class IGCTextData {
|
|||
/// Returns a list of [TextSpan]s used to display the text in the input field
|
||||
/// with the appropriate styling for each error match.
|
||||
List<TextSpan> constructTokenSpan({
|
||||
required BuildContext context,
|
||||
ChoreoRecordStep? choreoStep,
|
||||
TextStyle? defaultStyle,
|
||||
required SpanCardModel? spanCardModel,
|
||||
required bool handleClick,
|
||||
required String transformTargetId,
|
||||
required Room room,
|
||||
}) {
|
||||
final stepMatch = choreoStep?.acceptedOrIgnoredMatch;
|
||||
final List<PangeaMatch> textSpanMatches = List.from(matches);
|
||||
if (stepMatch != null && stepMatch.status == PangeaMatchStatus.automatic) {
|
||||
textSpanMatches.add(stepMatch);
|
||||
}
|
||||
|
||||
final List<TextSpan> items = [];
|
||||
|
||||
if (loading) {
|
||||
|
|
@ -381,7 +382,8 @@ class IGCTextData {
|
|||
];
|
||||
}
|
||||
|
||||
final List<List<int>> matchRanges = matches
|
||||
textSpanMatches.sort((a, b) => a.match.offset.compareTo(b.match.offset));
|
||||
final List<List<int>> matchRanges = textSpanMatches
|
||||
.map(
|
||||
(match) => [
|
||||
match.match.offset,
|
||||
|
|
@ -403,7 +405,7 @@ class IGCTextData {
|
|||
if (inMatch) {
|
||||
// if the pointer is in a match, then add that match to items
|
||||
// and then move the pointer to the end of the match range
|
||||
final PangeaMatch match = matches[matchIndex];
|
||||
final PangeaMatch match = textSpanMatches[matchIndex];
|
||||
items.add(
|
||||
getSpanItem(
|
||||
start: match.match.offset,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import '../constants/match_rule_ids.dart';
|
|||
import 'igc_text_data_model.dart';
|
||||
import 'span_data.dart';
|
||||
|
||||
enum PangeaMatchStatus { open, ignored, accepted, unknown }
|
||||
enum PangeaMatchStatus { open, ignored, accepted, automatic, unknown }
|
||||
|
||||
class PangeaMatch {
|
||||
SpanData match;
|
||||
|
|
@ -112,6 +112,10 @@ class PangeaMatch {
|
|||
offset >= match.offset && offset < match.offset + match.length;
|
||||
|
||||
Color get underlineColor {
|
||||
if (status == PangeaMatchStatus.automatic) {
|
||||
return const Color.fromARGB(187, 132, 96, 224);
|
||||
}
|
||||
|
||||
switch (match.rule?.id ?? "unknown") {
|
||||
case MatchRuleIds.interactiveTranslation:
|
||||
return const Color.fromARGB(187, 132, 96, 224);
|
||||
|
|
|
|||
|
|
@ -175,16 +175,14 @@ class PangeaTextController extends TextEditingController {
|
|||
return TextSpan(text: text, style: style);
|
||||
}
|
||||
|
||||
final choreoSteps = choreographer.choreoRecord.choreoSteps;
|
||||
|
||||
return TextSpan(
|
||||
style: style,
|
||||
children: [
|
||||
...choreographer.igc.igcTextData!.constructTokenSpan(
|
||||
context: context,
|
||||
choreoStep: choreoSteps.isNotEmpty ? choreoSteps.last : null,
|
||||
defaultStyle: style,
|
||||
spanCardModel: null,
|
||||
handleClick: false,
|
||||
transformTargetId: choreographer.inputTransformTargetKey,
|
||||
room: choreographer.chatController.room,
|
||||
),
|
||||
TextSpan(text: parts[1], style: style),
|
||||
],
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue