Merge branch 'main' into power-level-hotfix
This commit is contained in:
commit
8f557f7740
3 changed files with 109 additions and 26 deletions
|
|
@ -19,14 +19,37 @@ 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;
|
||||
|
||||
IgcController(this.choreographer);
|
||||
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();
|
||||
}
|
||||
|
||||
Future<void> getIGCTextData({required bool tokensOnly}) async {
|
||||
try {
|
||||
|
|
@ -80,6 +103,14 @@ class IgcController {
|
|||
|
||||
igcTextData = igcTextDataResponse;
|
||||
|
||||
// After fetching igc data, pre-call span details for each match optimistically.
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
debugPrint("igc text ${igcTextData.toString()}");
|
||||
} catch (err, stack) {
|
||||
debugger(when: kDebugMode);
|
||||
|
|
@ -99,18 +130,38 @@ class IgcController {
|
|||
debugger(when: kDebugMode);
|
||||
return;
|
||||
}
|
||||
final SpanData span = igcTextData!.matches[matchIndex].match;
|
||||
|
||||
final SpanDetailsRepoReqAndRes response = await SpanDataRepo.getSpanDetails(
|
||||
await choreographer.accessToken,
|
||||
request: SpanDetailsRepoReqAndRes(
|
||||
userL1: choreographer.l1LangCode!,
|
||||
userL2: choreographer.l2LangCode!,
|
||||
enableIGC: choreographer.igcEnabled,
|
||||
enableIT: choreographer.itEnabled,
|
||||
span: span,
|
||||
),
|
||||
/// 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;
|
||||
|
|
|
|||
|
|
@ -72,6 +72,24 @@ class SpanDetailsRepoReqAndRes {
|
|||
enableIGC: json['enable_igc'] as bool,
|
||||
span: SpanData.fromJson(json['span']),
|
||||
);
|
||||
|
||||
/// Overrides the equality operator to compare two [SpanDetailsRepoReqAndRes] objects.
|
||||
/// Returns true if the objects are identical or have the same property
|
||||
/// values (based on the results of the toJson function), false otherwise.
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
if (other is! SpanDetailsRepoReqAndRes) return false;
|
||||
|
||||
return toJson().toString() == other.toJson().toString();
|
||||
}
|
||||
|
||||
/// Overrides the hashCode getter to generate a hash code for the [SpanDetailsRepoReqAndRes] object.
|
||||
/// Used as keys in response cache in igc_controller.
|
||||
@override
|
||||
int get hashCode {
|
||||
return toJson().toString().hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
final spanDataRepomockSpan = SpanData(
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ class ToolbarDisplayController {
|
|||
}
|
||||
|
||||
void showToolbar(BuildContext context, {MessageMode? mode}) {
|
||||
bool toolbarUp = true;
|
||||
if (highlighted) return;
|
||||
if (controller.selectMode) {
|
||||
controller.clearSelectedEvents();
|
||||
|
|
@ -76,8 +77,22 @@ class ToolbarDisplayController {
|
|||
if (targetRenderBox != null) {
|
||||
final Size transformTargetSize = (targetRenderBox as RenderBox).size;
|
||||
messageWidth = transformTargetSize.width;
|
||||
final Offset targetOffset = (targetRenderBox).localToGlobal(Offset.zero);
|
||||
final double screenHeight = MediaQuery.of(context).size.height;
|
||||
toolbarUp = targetOffset.dy >= screenHeight / 2;
|
||||
}
|
||||
|
||||
final Widget overlayMessage = OverlayMessage(
|
||||
pangeaMessageEvent.event,
|
||||
timeline: pangeaMessageEvent.timeline,
|
||||
immersionMode: immersionMode,
|
||||
ownMessage: pangeaMessageEvent.ownMessage,
|
||||
toolbarController: this,
|
||||
width: messageWidth,
|
||||
nextEvent: nextEvent,
|
||||
previousEvent: previousEvent,
|
||||
);
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
Widget overlayEntry;
|
||||
if (toolbar == null) return;
|
||||
|
|
@ -88,18 +103,9 @@ class ToolbarDisplayController {
|
|||
? CrossAxisAlignment.end
|
||||
: CrossAxisAlignment.start,
|
||||
children: [
|
||||
toolbar!,
|
||||
toolbarUp ? toolbar! : overlayMessage,
|
||||
const SizedBox(height: 6),
|
||||
OverlayMessage(
|
||||
pangeaMessageEvent.event,
|
||||
timeline: pangeaMessageEvent.timeline,
|
||||
immersionMode: immersionMode,
|
||||
ownMessage: pangeaMessageEvent.ownMessage,
|
||||
toolbarController: this,
|
||||
width: messageWidth,
|
||||
nextEvent: nextEvent,
|
||||
previousEvent: previousEvent,
|
||||
),
|
||||
toolbarUp ? overlayMessage : toolbar!,
|
||||
],
|
||||
);
|
||||
} catch (err) {
|
||||
|
|
@ -113,11 +119,19 @@ class ToolbarDisplayController {
|
|||
child: overlayEntry,
|
||||
transformTargetId: targetId,
|
||||
targetAnchor: pangeaMessageEvent.ownMessage
|
||||
? Alignment.bottomRight
|
||||
: Alignment.bottomLeft,
|
||||
? toolbarUp
|
||||
? Alignment.bottomRight
|
||||
: Alignment.topRight
|
||||
: toolbarUp
|
||||
? Alignment.bottomLeft
|
||||
: Alignment.topLeft,
|
||||
followerAnchor: pangeaMessageEvent.ownMessage
|
||||
? Alignment.bottomRight
|
||||
: Alignment.bottomLeft,
|
||||
? toolbarUp
|
||||
? Alignment.bottomRight
|
||||
: Alignment.topRight
|
||||
: toolbarUp
|
||||
? Alignment.bottomLeft
|
||||
: Alignment.topLeft,
|
||||
backgroundColor: const Color.fromRGBO(0, 0, 0, 1).withAlpha(100),
|
||||
);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue