Merge branch 'main' into sentry-using-dart
This commit is contained in:
commit
fb211dd919
5 changed files with 134 additions and 97 deletions
|
|
@ -3,9 +3,9 @@ import 'dart:developer';
|
|||
|
||||
import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/controllers/error_service.dart';
|
||||
import 'package:fluffychat/pangea/controllers/span_data_controller.dart';
|
||||
import 'package:fluffychat/pangea/models/igc_text_data_model.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_match_model.dart';
|
||||
import 'package:fluffychat/pangea/models/span_data.dart';
|
||||
import 'package:fluffychat/pangea/repo/igc_repo.dart';
|
||||
import 'package:fluffychat/pangea/widgets/igc/span_card.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
|
@ -14,41 +14,19 @@ import 'package:sentry_flutter/sentry_flutter.dart';
|
|||
|
||||
import '../../models/language_detection_model.dart';
|
||||
import '../../models/span_card_model.dart';
|
||||
import '../../repo/span_data_repo.dart';
|
||||
import '../../repo/tokens_repo.dart';
|
||||
import '../../utils/error_handler.dart';
|
||||
import '../../utils/overlay.dart';
|
||||
|
||||
class _SpanDetailsCacheItem {
|
||||
SpanDetailsRepoReqAndRes data;
|
||||
|
||||
_SpanDetailsCacheItem({required this.data});
|
||||
}
|
||||
|
||||
class IgcController {
|
||||
Choreographer choreographer;
|
||||
IGCTextData? igcTextData;
|
||||
Object? igcError;
|
||||
|
||||
Completer<IGCTextData> igcCompleter = Completer();
|
||||
final Map<int, _SpanDetailsCacheItem> _cache = {};
|
||||
Timer? _cacheClearTimer;
|
||||
late SpanDataController spanDataController;
|
||||
|
||||
IgcController(this.choreographer) {
|
||||
_initializeCacheClearing();
|
||||
}
|
||||
|
||||
void _initializeCacheClearing() {
|
||||
const duration = Duration(minutes: 2);
|
||||
_cacheClearTimer = Timer.periodic(duration, (Timer t) => _clearCache());
|
||||
}
|
||||
|
||||
void _clearCache() {
|
||||
_cache.clear();
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
_cacheClearTimer?.cancel();
|
||||
spanDataController = SpanDataController(choreographer);
|
||||
}
|
||||
|
||||
Future<void> getIGCTextData({required bool tokensOnly}) async {
|
||||
|
|
@ -56,10 +34,8 @@ class IgcController {
|
|||
if (choreographer.currentText.isEmpty) return clear();
|
||||
|
||||
// the error spans are going to be reloaded, so clear the cache
|
||||
_clearCache();
|
||||
|
||||
spanDataController.clearCache();
|
||||
debugPrint('getIGCTextData called with ${choreographer.currentText}');
|
||||
|
||||
debugPrint('getIGCTextData called with tokensOnly = $tokensOnly');
|
||||
|
||||
final IGCRequestBody reqBody = IGCRequestBody(
|
||||
|
|
@ -110,7 +86,7 @@ class IgcController {
|
|||
// This will make the loading of span details faster for the user
|
||||
if (igcTextData?.matches.isNotEmpty ?? false) {
|
||||
for (int i = 0; i < igcTextData!.matches.length; i++) {
|
||||
getSpanDetails(i);
|
||||
spanDataController.getSpanDetails(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -125,56 +101,6 @@ class IgcController {
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> getSpanDetails(int matchIndex) async {
|
||||
if (igcTextData == null ||
|
||||
igcTextData!.matches.isEmpty ||
|
||||
matchIndex < 0 ||
|
||||
matchIndex >= igcTextData!.matches.length) {
|
||||
debugger(when: kDebugMode);
|
||||
return;
|
||||
}
|
||||
|
||||
/// Retrieves the span data from the `igcTextData` matches at the specified `matchIndex`.
|
||||
/// Creates a `SpanDetailsRepoReqAndRes` object with the retrieved span data and other parameters.
|
||||
/// Generates a cache key based on the created `SpanDetailsRepoReqAndRes` object.
|
||||
final SpanData span = igcTextData!.matches[matchIndex].match;
|
||||
final req = SpanDetailsRepoReqAndRes(
|
||||
userL1: choreographer.l1LangCode!,
|
||||
userL2: choreographer.l2LangCode!,
|
||||
enableIGC: choreographer.igcEnabled,
|
||||
enableIT: choreographer.itEnabled,
|
||||
span: span,
|
||||
);
|
||||
final int cacheKey = req.hashCode;
|
||||
|
||||
/// Retrieves the [SpanDetailsRepoReqAndRes] response from the cache if it exists,
|
||||
/// otherwise makes an API call to get the response and stores it in the cache.
|
||||
SpanDetailsRepoReqAndRes response;
|
||||
if (_cache.containsKey(cacheKey)) {
|
||||
response = _cache[cacheKey]!.data;
|
||||
} else {
|
||||
response = await SpanDataRepo.getSpanDetails(
|
||||
await choreographer.accessToken,
|
||||
request: SpanDetailsRepoReqAndRes(
|
||||
userL1: choreographer.l1LangCode!,
|
||||
userL2: choreographer.l2LangCode!,
|
||||
enableIGC: choreographer.igcEnabled,
|
||||
enableIT: choreographer.itEnabled,
|
||||
span: span,
|
||||
),
|
||||
);
|
||||
_cache[cacheKey] = _SpanDetailsCacheItem(data: response);
|
||||
}
|
||||
|
||||
try {
|
||||
igcTextData!.matches[matchIndex].match = response.span;
|
||||
} catch (err, s) {
|
||||
ErrorHandler.logError(e: err, s: s);
|
||||
}
|
||||
|
||||
choreographer.setState();
|
||||
}
|
||||
|
||||
Future<void> justGetTokensAndAddThemToIGCTextData() async {
|
||||
try {
|
||||
if (igcTextData == null) {
|
||||
|
|
@ -290,7 +216,7 @@ class IgcController {
|
|||
|
||||
clear() {
|
||||
igcTextData = null;
|
||||
_clearCache();
|
||||
spanDataController.clearCache();
|
||||
// Not sure why this is here
|
||||
// MatrixState.pAnyState.closeOverlay();
|
||||
}
|
||||
|
|
|
|||
89
lib/pangea/controllers/span_data_controller.dart
Normal file
89
lib/pangea/controllers/span_data_controller.dart
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart';
|
||||
import 'package:fluffychat/pangea/models/span_data.dart';
|
||||
import 'package:fluffychat/pangea/repo/span_data_repo.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
class _SpanDetailsCacheItem {
|
||||
Future<SpanDetailsRepoReqAndRes> data;
|
||||
|
||||
_SpanDetailsCacheItem({required this.data});
|
||||
}
|
||||
|
||||
class SpanDataController {
|
||||
late Choreographer choreographer;
|
||||
final Map<int, _SpanDetailsCacheItem> _cache = {};
|
||||
Timer? _cacheClearTimer;
|
||||
|
||||
SpanDataController(this.choreographer) {
|
||||
_initializeCacheClearing();
|
||||
}
|
||||
|
||||
void _initializeCacheClearing() {
|
||||
const duration = Duration(minutes: 2);
|
||||
_cacheClearTimer = Timer.periodic(duration, (Timer t) => clearCache());
|
||||
}
|
||||
|
||||
void clearCache() {
|
||||
_cache.clear();
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
_cacheClearTimer?.cancel();
|
||||
}
|
||||
|
||||
Future<void> getSpanDetails(int matchIndex) async {
|
||||
if (choreographer.igc.igcTextData == null ||
|
||||
choreographer.igc.igcTextData!.matches.isEmpty ||
|
||||
matchIndex < 0 ||
|
||||
matchIndex >= choreographer.igc.igcTextData!.matches.length) {
|
||||
debugger(when: kDebugMode);
|
||||
return;
|
||||
}
|
||||
|
||||
/// Retrieves the span data from the `igcTextData` matches at the specified `matchIndex`.
|
||||
/// Creates a `SpanDetailsRepoReqAndRes` object with the retrieved span data and other parameters.
|
||||
/// Generates a cache key based on the created `SpanDetailsRepoReqAndRes` object.
|
||||
final SpanData span =
|
||||
choreographer.igc.igcTextData!.matches[matchIndex].match;
|
||||
final req = SpanDetailsRepoReqAndRes(
|
||||
userL1: choreographer.l1LangCode!,
|
||||
userL2: choreographer.l2LangCode!,
|
||||
enableIGC: choreographer.igcEnabled,
|
||||
enableIT: choreographer.itEnabled,
|
||||
span: span,
|
||||
);
|
||||
final int cacheKey = req.hashCode;
|
||||
|
||||
/// Retrieves the [SpanDetailsRepoReqAndRes] response from the cache if it exists,
|
||||
/// otherwise makes an API call to get the response and stores it in the cache.
|
||||
Future<SpanDetailsRepoReqAndRes> response;
|
||||
if (_cache.containsKey(cacheKey)) {
|
||||
response = _cache[cacheKey]!.data;
|
||||
} else {
|
||||
response = SpanDataRepo.getSpanDetails(
|
||||
await choreographer.accessToken,
|
||||
request: SpanDetailsRepoReqAndRes(
|
||||
userL1: choreographer.l1LangCode!,
|
||||
userL2: choreographer.l2LangCode!,
|
||||
enableIGC: choreographer.igcEnabled,
|
||||
enableIT: choreographer.itEnabled,
|
||||
span: span,
|
||||
),
|
||||
);
|
||||
_cache[cacheKey] = _SpanDetailsCacheItem(data: response);
|
||||
}
|
||||
|
||||
try {
|
||||
choreographer.igc.igcTextData!.matches[matchIndex].match =
|
||||
(await response).span;
|
||||
} catch (err, s) {
|
||||
ErrorHandler.logError(e: err, s: s);
|
||||
}
|
||||
|
||||
choreographer.setState();
|
||||
}
|
||||
}
|
||||
|
|
@ -148,6 +148,30 @@ class SpanChoice {
|
|||
bool get isBestCorrection => type == SpanChoiceType.bestCorrection;
|
||||
|
||||
Color get color => type.color;
|
||||
|
||||
// override == operator and hashcode
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other is SpanChoice &&
|
||||
other.value == value &&
|
||||
other.type.toString() == type.toString() &&
|
||||
other.selected == selected &&
|
||||
other.feedback == feedback &&
|
||||
other.timestamp?.toIso8601String() == timestamp?.toIso8601String();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return Object.hashAll([
|
||||
value.hashCode,
|
||||
type.toString().hashCode,
|
||||
selected.hashCode,
|
||||
feedback.hashCode,
|
||||
timestamp?.toIso8601String().hashCode,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
class Rule {
|
||||
|
|
|
|||
|
|
@ -85,16 +85,13 @@ class SpanDetailsRepoReqAndRes {
|
|||
if (other.userL2 != userL2) return false;
|
||||
if (other.enableIT != enableIT) return false;
|
||||
if (other.enableIGC != enableIGC) return false;
|
||||
if (other.span.choices
|
||||
?.firstWhere(
|
||||
(choice) => choice.type == SpanChoiceType.bestCorrection,
|
||||
)
|
||||
.value !=
|
||||
span.choices
|
||||
?.firstWhere(
|
||||
(choice) => choice.type == SpanChoiceType.bestCorrection,
|
||||
)
|
||||
.value) return false;
|
||||
if (const ListEquality().equals(
|
||||
other.span.choices?.sorted((a, b) => b.value.compareTo(a.value)),
|
||||
span.choices?.sorted((a, b) => b.value.compareTo(a.value)),
|
||||
) ==
|
||||
false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -107,12 +104,12 @@ class SpanDetailsRepoReqAndRes {
|
|||
userL2.hashCode,
|
||||
enableIT.hashCode,
|
||||
enableIGC.hashCode,
|
||||
span.choices
|
||||
?.firstWhereOrNull(
|
||||
(choice) => choice.type == SpanChoiceType.bestCorrection,
|
||||
)
|
||||
?.value
|
||||
.hashCode,
|
||||
if (span.choices != null)
|
||||
Object.hashAll(
|
||||
span.choices!
|
||||
.sorted((a, b) => b.value.compareTo(a.value))
|
||||
.map((choice) => choice.hashCode),
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,7 +94,8 @@ class SpanCardState extends State<SpanCard> {
|
|||
fetchingData = true;
|
||||
});
|
||||
|
||||
await widget.scm.choreographer.igc.getSpanDetails(widget.scm.matchIndex);
|
||||
await widget.scm.choreographer.igc.spanDataController
|
||||
.getSpanDetails(widget.scm.matchIndex);
|
||||
|
||||
if (mounted) {
|
||||
setState(() => fetchingData = false);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue