import 'dart:async'; import 'package:fluffychat/pangea/controllers/base_controller.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; import 'package:fluffychat/pangea/models/pangea_token_model.dart'; import 'package:fluffychat/pangea/models/representation_content_model.dart'; import 'package:fluffychat/pangea/models/tokens_event_content_model.dart'; import 'package:fluffychat/pangea/repo/tokens_repo.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:matrix/matrix.dart'; import '../constants/pangea_event_types.dart'; import '../repo/full_text_translation_repo.dart'; import '../utils/error_handler.dart'; // TODO - make this static and take it out of the _pangeaController // will need to pass accessToken to the requests class MessageDataController extends BaseController { late PangeaController _pangeaController; final Map>> _tokensCache = {}; final Map> _representationCache = {}; late Timer _cacheTimer; MessageDataController(PangeaController pangeaController) { _pangeaController = pangeaController; _startCacheTimer(); } /// Starts a timer that clears the cache every 10 minutes void _startCacheTimer() { _cacheTimer = Timer.periodic(const Duration(minutes: 10), (timer) { _clearCache(); }); } /// Clears the token and representation caches void _clearCache() { _tokensCache.clear(); _representationCache.clear(); debugPrint("message data cache cleared."); } @override void dispose() { _cacheTimer.cancel(); // Cancel the timer when the controller is disposed super.dispose(); } /// get tokens from the server /// if repEventId is not null, send the tokens to the room Future> _getTokens({ required String? repEventId, required TokensRequestModel req, required Room? room, }) async { final TokensResponseModel res = await TokensRepo.tokenize( _pangeaController.userController.accessToken, req, ); if (repEventId != null && room != null) { room .sendPangeaEvent( content: PangeaMessageTokens(tokens: res.tokens).toJson(), parentEventId: repEventId, type: PangeaEventTypes.tokens, ) .catchError( (e) => ErrorHandler.logError( m: "error in _getTokens.sendPangeaEvent", e: e, s: StackTrace.current, data: req.toJson(), ), ); } return res.tokens; } /// get tokens from the server /// first check if the tokens are in the cache /// if repEventId is not null, send the tokens to the room Future> getTokens({ required String? repEventId, required TokensRequestModel req, required Room? room, }) => _tokensCache[req.hashCode] ??= _getTokens( repEventId: repEventId, req: req, room: room, ); /////// translation //////// /// get translation from the server /// if in cache, return from cache /// if not in cache, get from server /// send the translation to the room as a representation event Future getPangeaRepresentation({ required FullTextTranslationRequestModel req, required Event messageEvent, }) async { return _representationCache[req.hashCode] ??= _getPangeaRepresentation(req: req, messageEvent: messageEvent); } Future _getPangeaRepresentation({ required FullTextTranslationRequestModel req, required Event messageEvent, }) async { final FullTextTranslationResponseModel res = await FullTextTranslationRepo.translate( accessToken: _pangeaController.userController.accessToken, request: req, ); final rep = PangeaRepresentation( langCode: req.tgtLang, text: res.bestTranslation, originalSent: false, originalWritten: false, ); messageEvent.room .sendPangeaEvent( content: rep.toJson(), parentEventId: messageEvent.eventId, type: PangeaEventTypes.representation, ) .catchError( (e) => ErrorHandler.logError( m: "error in _getPangeaRepresentation.sendPangeaEvent", e: e, s: StackTrace.current, data: req.toJson(), ), ); return rep; } }