Merge pull request #948 from pangeachat/sentry

reset room in startBotChat function after waiting for it in sync
This commit is contained in:
ggurdin 2024-11-12 11:04:08 -05:00 committed by GitHub
commit 2d2f063ba9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 91 additions and 74 deletions

View file

@ -7,7 +7,6 @@ import 'package:fluffychat/config/themes.dart';
import 'package:fluffychat/pages/chat/send_file_dialog.dart';
import 'package:fluffychat/pages/chat_list/chat_list_view.dart';
import 'package:fluffychat/pangea/constants/pangea_room_types.dart';
import 'package:fluffychat/pangea/controllers/pangea_controller.dart';
import 'package:fluffychat/pangea/extensions/client_extension/client_extension.dart';
import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart';
import 'package:fluffychat/pangea/utils/chat_list_handle_space_tap.dart';
@ -1016,7 +1015,7 @@ class ChatListController extends State<ChatList>
}
// #Pangea
await _initPangeaControllers(client);
_initPangeaControllers(client);
// Pangea#
if (!mounted) return;
setState(() {
@ -1025,22 +1024,12 @@ class ChatListController extends State<ChatList>
}
// #Pangea
Future<void> _initPangeaControllers(Client client) async {
MatrixState.pangeaController.putAnalytics.initialize();
MatrixState.pangeaController.getAnalytics.initialize();
void _initPangeaControllers(Client client) {
GoogleAnalytics.analyticsUserUpdate(client.userID);
client.migrateAnalyticsRooms();
MatrixState.pangeaController.initControllers();
if (mounted) {
final PangeaController pangeaController = MatrixState.pangeaController;
GoogleAnalytics.analyticsUserUpdate(client.userID);
pangeaController.startChatWithBotIfNotPresent();
await pangeaController.subscriptionController.initialize();
pangeaController.afterSyncAndFirstLoginInitialization(context);
await pangeaController.inviteBotToExistingSpaces();
await pangeaController.setPangeaPushRules();
client.migrateAnalyticsRooms();
} else {
ErrorHandler.logError(
m: "didn't run afterSyncAndFirstLoginInitialization because not mounted",
);
MatrixState.pangeaController.classController.joinCachedSpaceCode(context);
}
}
// Pangea#

View file

@ -42,7 +42,7 @@ class ClassController extends BaseController {
);
}
Future<void> checkForClassCodeAndSubscription(BuildContext context) async {
Future<void> joinCachedSpaceCode(BuildContext context) async {
final String? classCode = _pangeaController.pStoreService.read(
PLocalKey.cachedClassCodeToJoin,
isAccountData: false,
@ -53,6 +53,7 @@ class ClassController extends BaseController {
context,
classCode,
);
await _pangeaController.pStoreService.delete(
PLocalKey.cachedClassCodeToJoin,
isAccountData: false,

View file

@ -25,6 +25,7 @@ class GetAnalyticsController {
StreamController.broadcast();
ConstructListModel constructListModel = ConstructListModel(uses: []);
Completer<void>? initCompleter;
GetAnalyticsController(PangeaController pangeaController) {
_pangeaController = pangeaController;
@ -34,13 +35,19 @@ class GetAnalyticsController {
Client get _client => _pangeaController.matrixState.client;
// the minimum XP required for a given level
double get _minXPForLevel {
return 12.5 * (2 * pow(constructListModel.level - 1, 2) - 1);
int get _minXPForLevel {
return _calculateMinXpForLevel(constructListModel.level);
}
// the minimum XP required for the next level
double get _minXPForNextLevel {
return 12.5 * (2 * pow(constructListModel.level, 2) - 1);
int get _minXPForNextLevel {
return _calculateMinXpForLevel(constructListModel.level + 1);
}
/// Calculates the minimum XP required for a specific level.
int _calculateMinXpForLevel(int level) {
if (level == 1) return 0; // Ensure level 1 starts at 0 XP
return ((100 / 8) * (2 * pow(level - 1, 2))).floor();
}
// the progress within the current level as a percentage (0.0 to 1.0)
@ -50,20 +57,23 @@ class GetAnalyticsController {
return progress >= 0 ? progress : 0;
}
void initialize() {
Future<void> initialize() async {
if (initCompleter != null) return;
initCompleter = Completer<void>();
_analyticsUpdateSubscription ??= _pangeaController
.putAnalytics.analyticsUpdateStream.stream
.listen(_onAnalyticsUpdate);
_pangeaController.putAnalytics.lastUpdatedCompleter.future.then((_) {
_getConstructs().then((_) {
constructListModel.updateConstructs([
...(_getConstructsLocal() ?? []),
..._locallyCachedConstructs,
]);
_updateAnalyticsStream();
});
});
await _pangeaController.putAnalytics.lastUpdatedCompleter.future;
await _getConstructs();
constructListModel.updateConstructs([
...(_getConstructsLocal() ?? []),
..._locallyCachedConstructs,
]);
_updateAnalyticsStream();
initCompleter!.complete();
}
/// Clear all cached analytics data.
@ -71,6 +81,7 @@ class GetAnalyticsController {
constructListModel.dispose();
_analyticsUpdateSubscription?.cancel();
_analyticsUpdateSubscription = null;
initCompleter = null;
_cache.clear();
}

View file

@ -28,7 +28,6 @@ import 'package:fluffychat/pangea/utils/bot_name.dart';
import 'package:fluffychat/pangea/utils/error_handler.dart';
import 'package:fluffychat/pangea/utils/instructions.dart';
import 'package:fluffychat/widgets/matrix.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:matrix/matrix.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
@ -80,11 +79,19 @@ class PangeaController {
_addRefInObjects();
}
Future<void> afterSyncAndFirstLoginInitialization(
BuildContext context,
) async {
await classController.checkForClassCodeAndSubscription(context);
/// Initializes various controllers and settings.
/// While many of these functions are asynchronous, they are not awaited here,
/// because of order of execution does not matter,
/// and running them at the same times speeds them up.
void initControllers() {
putAnalytics.initialize();
getAnalytics.initialize();
subscriptionController.initialize();
classController.fixClassPowerLevels();
startChatWithBotIfNotPresent();
inviteBotToExistingSpaces();
setPangeaPushRules();
}
/// Initialize controllers
@ -243,13 +250,23 @@ class PangeaController {
],
);
final room = matrixState.client.getRoomById(roomId);
Room? room = matrixState.client.getRoomById(roomId);
if (room == null || room.membership != Membership.join) {
// Wait for room actually appears in sync
await matrixState.client.waitForRoomInSync(roomId, join: true);
room = matrixState.client.getRoomById(roomId);
if (room == null) {
ErrorHandler.logError(
e: "Bot chat null after waiting for room in sync",
data: {
"roomId": roomId,
},
);
return null;
}
}
final botOptions = room!.getState(PangeaEventTypes.botOptions);
final botOptions = room.getState(PangeaEventTypes.botOptions);
if (botOptions == null) {
await matrixState.client.setRoomStateWithKey(
roomId,
@ -277,7 +294,10 @@ class PangeaController {
}
final Room botDMWithLatestActivity = botDMs.reduce((a, b) {
if (a.timeline == null || b.timeline == null) {
if (a.timeline == null ||
b.timeline == null ||
a.timeline!.events.isEmpty ||
b.timeline!.events.isEmpty) {
return a;
}
final aLastEvent = a.timeline!.events.last;

View file

@ -146,7 +146,7 @@ class PutAnalyticsController extends BaseController<AnalyticsStream> {
);
}
Future<void> _onUpdateLanguages(String previousL2) async {
Future<void> _onUpdateLanguages(String? previousL2) async {
await sendLocalAnalyticsToAnalyticsRoom(
l2Override: previousL2,
);

View file

@ -137,11 +137,11 @@ class SignupPageController extends State<SignupPage> {
displayname,
);
}
} catch (e) {
} catch (e, s) {
//#Pangea
const cancelledString = "Exception: Request has been canceled";
if (e.toString() != cancelledString) {
ErrorHandler.logError(e: e);
ErrorHandler.logError(e: e, s: s);
error = (e).toLocalizedString(context);
}
// Pangea#

View file

@ -41,13 +41,8 @@ Future<void> downloadChat(
timeline,
room,
);
} catch (err) {
ErrorHandler.logError(
e: Exception(
"Failed to fetch messages for chat ${room.id} in while downloading chat",
),
s: StackTrace.current,
);
} catch (err, s) {
ErrorHandler.logError(e: err, s: s);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
@ -214,12 +209,9 @@ Future<void> downloadFile(
directory = await getExternalStorageDirectory();
}
}
} catch (err) {
} catch (err, s) {
debugPrint("Failed to get download folder path");
ErrorHandler.logError(
e: Exception("Failed to get download folder path"),
s: StackTrace.current,
);
ErrorHandler.logError(e: err, s: s);
}
if (directory != null) {
final File f = File("${directory.path}/$filename");

View file

@ -1,5 +1,4 @@
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/pangea/controllers/pangea_controller.dart';
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart';
import 'package:fluffychat/pangea/models/pangea_token_model.dart';
import 'package:fluffychat/pangea/widgets/chat/message_selection_overlay.dart';
@ -24,26 +23,24 @@ class OverlayMessageText extends StatefulWidget {
}
class OverlayMessageTextState extends State<OverlayMessageText> {
final PangeaController pangeaController = MatrixState.pangeaController;
List<PangeaToken>? tokens;
List<PangeaToken>? _tokens;
@override
void initState() {
super.initState();
_setTokens();
}
Future<void> _setTokens() async {
final repEvent = widget.pangeaMessageEvent.messageDisplayRepresentation;
if (repEvent != null) {
tokens = repEvent.tokens;
if (tokens == null) {
repEvent
.tokensGlobal(
widget.pangeaMessageEvent.senderId,
widget.pangeaMessageEvent.originServerTs,
)
.then((tokens) {
setState(() => this.tokens = tokens);
});
}
_tokens = repEvent.tokens;
_tokens ??= await repEvent.tokensGlobal(
widget.pangeaMessageEvent.senderId,
widget.pangeaMessageEvent.originServerTs,
);
if (mounted) setState(() {});
}
super.initState();
}
@override
@ -60,7 +57,7 @@ class OverlayMessageTextState extends State<OverlayMessageText> {
fontSize: AppConfig.messageFontSize * AppConfig.fontSizeFactor,
);
if (tokens == null || tokens!.isEmpty) {
if (_tokens == null || _tokens!.isEmpty) {
return Text(
widget.pangeaMessageEvent.event.calcLocalizedBodyFallback(
MatrixLocals(L10n.of(context)!),
@ -83,8 +80,8 @@ class OverlayMessageTextState extends State<OverlayMessageText> {
final List<TokenPosition> tokenPositions = [];
int globalIndex = 0;
for (int i = 0; i < tokens!.length; i++) {
final token = tokens![i];
for (int i = 0; i < _tokens!.length; i++) {
final token = _tokens![i];
final start = token.start;
final end = token.end;

View file

@ -36,6 +36,13 @@ class LearningProgressIndicatorsState
@override
void initState() {
super.initState();
// if getAnalytics has already finished initializing,
// the data is loaded and should be displayed.
if (MatrixState.pangeaController.getAnalytics.initCompleter?.isCompleted ??
false) {
updateData(null);
}
_analyticsSubscription = MatrixState
.pangeaController.getAnalytics.analyticsStream.stream
.listen(updateData);
@ -48,7 +55,7 @@ class LearningProgressIndicatorsState
super.dispose();
}
void updateData(AnalyticsStreamUpdate _) {
void updateData(AnalyticsStreamUpdate? _) {
if (_loading) _loading = false;
if (mounted) setState(() {});
}