better documentation
This commit is contained in:
parent
14b89594c2
commit
ab8387c522
5 changed files with 67 additions and 95 deletions
|
|
@ -407,7 +407,7 @@ class Choreographer extends ChangeNotifier {
|
|||
|
||||
void clearMatches(Object error) {
|
||||
MatrixState.pAnyState.closeAllOverlays();
|
||||
igcController.clearMatches();
|
||||
igcController.clearIGCMatches();
|
||||
errorService.setError(ChoreoError(raw: error));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/controllers/extensions/choregrapher_user_settings_extension.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/enums/assistance_state_enum.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/enums/choreo_mode.dart';
|
||||
|
||||
|
|
@ -28,38 +27,4 @@ extension ChoregrapherUserSettingsExtension on Choreographer {
|
|||
if (!igcController.hasIGCTextData) return AssistanceState.notFetched;
|
||||
return AssistanceState.complete;
|
||||
}
|
||||
|
||||
bool get canSendMessage {
|
||||
// if there's an error, let them send. we don't want to block them from sending in this case
|
||||
if (errorService.isError ||
|
||||
l2Lang == null ||
|
||||
l1Lang == null ||
|
||||
timesClicked > 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// if they're in IT mode, don't let them send
|
||||
if (itEnabled && isRunningIT) return false;
|
||||
|
||||
// if they've turned off IGC then let them send the message when they want
|
||||
if (!isAutoIGCEnabled) return true;
|
||||
|
||||
// if we're in the middle of fetching results, don't let them send
|
||||
if (isFetching.value) return false;
|
||||
|
||||
// they're supposed to run IGC but haven't yet, don't let them send
|
||||
if (!igcController.hasIGCTextData) {
|
||||
return itController.dismissed;
|
||||
}
|
||||
|
||||
// if they have relevant matches, don't let them send
|
||||
final hasITMatches = igcController.hasOpenITMatches;
|
||||
final hasIGCMatches = igcController.hasOpenIGCMatches;
|
||||
if ((itEnabled && hasITMatches) || (igcEnabled && hasIGCMatches)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// otherwise, let them send
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,10 +23,8 @@ class IgcController {
|
|||
|
||||
String? get currentText => _igcTextData?.currentText;
|
||||
bool get hasOpenMatches => _igcTextData?.hasOpenMatches == true;
|
||||
bool get hasOpenITMatches => _igcTextData?.hasOpenITMatches == true;
|
||||
bool get hasOpenIGCMatches => _igcTextData?.hasOpenIGCMatches == true;
|
||||
|
||||
PangeaMatchState? get openMatch => _igcTextData?.openMatch;
|
||||
PangeaMatchState? get currentlyOpenMatch => _igcTextData?.currentlyOpenMatch;
|
||||
PangeaMatchState? get firstOpenMatch => _igcTextData?.firstOpenMatch;
|
||||
List<PangeaMatchState>? get openMatches => _igcTextData?.openMatches;
|
||||
List<PangeaMatchState>? get recentNormalizationMatches =>
|
||||
|
|
@ -43,10 +41,10 @@ class IgcController {
|
|||
MatrixState.pAnyState.closeAllOverlays();
|
||||
}
|
||||
|
||||
void clearMatches() => _igcTextData?.clearMatches();
|
||||
void clearIGCMatches() => _igcTextData?.clearIGCMatches();
|
||||
|
||||
PangeaMatchState? getMatchByOffset(int offset) =>
|
||||
_igcTextData?.getMatchByOffset(offset);
|
||||
_igcTextData?.getOpenMatchByOffset(offset);
|
||||
|
||||
PangeaMatch acceptReplacement(
|
||||
PangeaMatchState match,
|
||||
|
|
@ -55,7 +53,7 @@ class IgcController {
|
|||
if (_igcTextData == null) {
|
||||
throw "acceptReplacement called with null igcTextData";
|
||||
}
|
||||
final updateMatch = _igcTextData!.acceptReplacement(match, status);
|
||||
final updateMatch = _igcTextData!.makeAcceptedMatchUpdates(match, status);
|
||||
return updateMatch;
|
||||
}
|
||||
|
||||
|
|
@ -64,14 +62,14 @@ class IgcController {
|
|||
if (_igcTextData == null) {
|
||||
throw "should not be in onIgnoreMatch with null igcTextData";
|
||||
}
|
||||
return _igcTextData!.ignoreReplacement(match);
|
||||
return _igcTextData!.makeIgnoredMatchUpdates(match);
|
||||
}
|
||||
|
||||
void undoReplacement(PangeaMatchState match) {
|
||||
if (_igcTextData == null) {
|
||||
throw "undoReplacement called with null igcTextData";
|
||||
}
|
||||
_igcTextData!.undoReplacement(match);
|
||||
_igcTextData!.removeMatchUpdates(match);
|
||||
}
|
||||
|
||||
Future<void> getIGCTextData(
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ class PangeaTextController extends TextEditingController {
|
|||
}
|
||||
|
||||
final openMatch =
|
||||
choreographer.igcController.openMatch?.updatedMatch.match;
|
||||
choreographer.igcController.currentlyOpenMatch?.updatedMatch.match;
|
||||
final style = _textStyle(
|
||||
match.updatedMatch,
|
||||
defaultStyle,
|
||||
|
|
|
|||
|
|
@ -9,45 +9,47 @@ import 'package:fluffychat/pangea/choreographer/models/span_data.dart';
|
|||
import 'package:fluffychat/pangea/choreographer/repo/igc_repo.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
||||
/// A model representing the mutable text and match state used by
|
||||
/// Interactive Grammar Correction (IGC).
|
||||
///
|
||||
/// This class tracks the original input text, the current working text,
|
||||
/// and the states of open and closed grammar matches as the user accepts,
|
||||
/// ignores, or reverses suggested corrections.
|
||||
class IGCTextData {
|
||||
/// The user's original text before any corrections or replacements.
|
||||
final String _originalInput;
|
||||
|
||||
/// The full list of detected matches from the initial grammar analysis.
|
||||
final List<PangeaMatch> _matches;
|
||||
|
||||
String _currentText;
|
||||
/// Matches currently pending user action (neither accepted nor ignored).
|
||||
final List<PangeaMatchState> _openMatches = [];
|
||||
|
||||
/// Matches that have been resolved by either accepting or ignoring them.
|
||||
final List<PangeaMatchState> _closedMatches = [];
|
||||
|
||||
/// The current text content after applying all accepted corrections.
|
||||
String _currentText;
|
||||
|
||||
IGCTextData({
|
||||
required String originalInput,
|
||||
required List<PangeaMatch> matches,
|
||||
}) : _currentText = originalInput,
|
||||
_originalInput = originalInput,
|
||||
_matches = matches {
|
||||
_openMatches.addAll(
|
||||
matches
|
||||
.where((match) => match.status == PangeaMatchStatus.open)
|
||||
.map((match) {
|
||||
return PangeaMatchState(
|
||||
match: match.match,
|
||||
status: match.status,
|
||||
original: match,
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
_closedMatches.addAll(
|
||||
matches
|
||||
.where((match) => match.status != PangeaMatchStatus.open)
|
||||
.map((match) {
|
||||
return PangeaMatchState(
|
||||
match: match.match,
|
||||
status: match.status,
|
||||
original: match,
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
_filterIgnoredMatches();
|
||||
for (final match in matches) {
|
||||
final matchState = PangeaMatchState(
|
||||
match: match.match,
|
||||
status: PangeaMatchStatus.open,
|
||||
original: match,
|
||||
);
|
||||
if (match.status == PangeaMatchStatus.open) {
|
||||
_openMatches.add(matchState);
|
||||
} else {
|
||||
_closedMatches.add(matchState);
|
||||
}
|
||||
}
|
||||
_filterPreviouslyIgnoredMatches();
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
|
|
@ -59,35 +61,33 @@ class IGCTextData {
|
|||
|
||||
List<PangeaMatchState> get openMatches => _openMatches;
|
||||
|
||||
List<PangeaMatchState> get closedMatches => _closedMatches;
|
||||
bool get hasOpenMatches => _openMatches.isNotEmpty;
|
||||
|
||||
PangeaMatchState? get firstOpenMatch => _openMatches.firstOrNull;
|
||||
|
||||
/// Normalization matches that have been closed in the last choreo step(s).
|
||||
/// Used to display automatic corrections made by the IGC system.
|
||||
List<PangeaMatchState> get recentNormalizationMatches =>
|
||||
closedMatches.reversed
|
||||
_closedMatches.reversed
|
||||
.takeWhile(
|
||||
(m) => m.updatedMatch.status == PangeaMatchStatus.automatic,
|
||||
)
|
||||
.toList();
|
||||
|
||||
/// Convenience getter for open normalization error matches.
|
||||
/// Used for auto-correction of normalization errors.
|
||||
List<PangeaMatchState> get openNormalizationMatches => _openMatches
|
||||
.where((match) => match.updatedMatch.match.isNormalizationError())
|
||||
.toList();
|
||||
|
||||
bool get hasOpenMatches => _openMatches.isNotEmpty;
|
||||
|
||||
bool get hasOpenITMatches =>
|
||||
_openMatches.any((match) => match.updatedMatch.isITStart);
|
||||
|
||||
bool get hasOpenIGCMatches =>
|
||||
_openMatches.any((match) => !match.updatedMatch.isITStart);
|
||||
|
||||
PangeaMatchState? get firstOpenMatch => _openMatches.firstOrNull;
|
||||
|
||||
PangeaMatchState? getMatchByOffset(int offset) =>
|
||||
/// Returns the open match that contains the given text offset, if any.
|
||||
PangeaMatchState? getOpenMatchByOffset(int offset) =>
|
||||
_openMatches.firstWhereOrNull(
|
||||
(match) => match.updatedMatch.match.isOffsetInMatchSpan(offset),
|
||||
);
|
||||
|
||||
PangeaMatchState? get openMatch {
|
||||
/// Returns the match whose span card overlay is currently open, if any.
|
||||
PangeaMatchState? get currentlyOpenMatch {
|
||||
final RegExp pattern = RegExp(r'span_card_overlay_.+');
|
||||
final String? matchingKeys =
|
||||
MatrixState.pAnyState.getMatchingOverlayKeys(pattern).firstOrNull;
|
||||
|
|
@ -105,19 +105,23 @@ class IGCTextData {
|
|||
);
|
||||
}
|
||||
|
||||
void clearMatches() {
|
||||
/// Clears all matches from the IGC text data.
|
||||
/// Call on error that make continuing IGC processing invalid.
|
||||
void clearIGCMatches() {
|
||||
_openMatches.clear();
|
||||
_closedMatches.clear();
|
||||
}
|
||||
|
||||
void _filterIgnoredMatches() {
|
||||
/// Filters out previously ignored matches from the open matches list.
|
||||
void _filterPreviouslyIgnoredMatches() {
|
||||
for (final match in _openMatches) {
|
||||
if (IgcRepo.isIgnored(match.updatedMatch)) {
|
||||
ignoreReplacement(match);
|
||||
makeIgnoredMatchUpdates(match);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Replaces the span data for a given match.
|
||||
void setSpanData(PangeaMatchState match, SpanData spanData) {
|
||||
final openMatch = _openMatches.firstWhereOrNull(
|
||||
(m) => m.originalMatch == match.originalMatch,
|
||||
|
|
@ -128,7 +132,9 @@ class IGCTextData {
|
|||
_openMatches.add(match);
|
||||
}
|
||||
|
||||
PangeaMatch acceptReplacement(
|
||||
/// Accepts the specified [match] and updates both the open/closed match lists
|
||||
/// and the [_currentText] to include the chosen replacement text.
|
||||
PangeaMatch makeAcceptedMatchUpdates(
|
||||
PangeaMatchState match,
|
||||
PangeaMatchStatus status,
|
||||
) {
|
||||
|
|
@ -158,11 +164,12 @@ class IGCTextData {
|
|||
return match.updatedMatch;
|
||||
}
|
||||
|
||||
PangeaMatch ignoreReplacement(PangeaMatchState match) {
|
||||
/// Ignores a given match and updates the IGC text data state accordingly.
|
||||
PangeaMatch makeIgnoredMatchUpdates(PangeaMatchState match) {
|
||||
final openMatch = _openMatches.firstWhere(
|
||||
(m) => m.originalMatch == match.originalMatch,
|
||||
orElse: () => throw Exception(
|
||||
'No open match found for ignoreReplacement',
|
||||
'No open match found for makeIgnoredMatchUpdates',
|
||||
),
|
||||
);
|
||||
|
||||
|
|
@ -172,21 +179,22 @@ class IGCTextData {
|
|||
return match.updatedMatch;
|
||||
}
|
||||
|
||||
void undoReplacement(PangeaMatchState match) {
|
||||
/// Removes a given match from the closed match history and undoes the
|
||||
/// changes to igc text data state caused by accepting the match.
|
||||
void removeMatchUpdates(PangeaMatchState match) {
|
||||
final closedMatch = _closedMatches.firstWhere(
|
||||
(m) => m.originalMatch == match.originalMatch,
|
||||
orElse: () => throw Exception(
|
||||
'No closed match found for undoReplacement',
|
||||
'No closed match found for removeMatchUpdates',
|
||||
),
|
||||
);
|
||||
|
||||
_closedMatches.remove(closedMatch);
|
||||
|
||||
final choice = match.updatedMatch.match.selectedChoice?.value;
|
||||
|
||||
if (choice == null) {
|
||||
throw Exception(
|
||||
"match.match.selectedChoice is null in undoReplacement",
|
||||
"match.match.selectedChoice is null in removeMatchUpdates",
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -204,6 +212,7 @@ class IGCTextData {
|
|||
);
|
||||
}
|
||||
|
||||
/// Runs a text replacement and updates match offsets / current text accordingly.
|
||||
void _runReplacement(
|
||||
int offset,
|
||||
int length,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue