added handling for all cases of null check
This commit is contained in:
parent
7655a978e8
commit
cba510ee76
37 changed files with 309 additions and 240 deletions
|
|
@ -247,7 +247,8 @@ class ChatController extends State<ChatPageWithRoom>
|
|||
// #Pangea
|
||||
// void requestHistory() async {
|
||||
Future<void> requestHistory() async {
|
||||
// #Pangea
|
||||
if (timeline == null) return;
|
||||
// Pangea#
|
||||
if (!timeline!.canRequestHistory) return;
|
||||
Logs().v('Requesting history...');
|
||||
await timeline!.requestHistory(historyCount: _loadHistoryCount);
|
||||
|
|
@ -425,7 +426,7 @@ class ChatController extends State<ChatPageWithRoom>
|
|||
numRequests++;
|
||||
}
|
||||
}
|
||||
// #Pangea
|
||||
// Pangea#
|
||||
} catch (e, s) {
|
||||
Logs().w('Unable to load timeline on event ID $eventContextId', e, s);
|
||||
if (!mounted) return;
|
||||
|
|
@ -1575,13 +1576,27 @@ class ChatController extends State<ChatPageWithRoom>
|
|||
setPangeaMessageEvent(eventId);
|
||||
if (_pangeaMessageEvents[eventId] == null) return;
|
||||
}
|
||||
_toolbarDisplayControllers[eventId] = ToolbarDisplayController(
|
||||
targetId: event.eventId,
|
||||
pangeaMessageEvent: _pangeaMessageEvents[eventId]!,
|
||||
immersionMode: choreographer.immersionMode,
|
||||
controller: this,
|
||||
);
|
||||
_toolbarDisplayControllers[eventId]!.setToolbar();
|
||||
|
||||
try {
|
||||
_toolbarDisplayControllers[eventId] = ToolbarDisplayController(
|
||||
targetId: event.eventId,
|
||||
pangeaMessageEvent: _pangeaMessageEvents[eventId]!,
|
||||
immersionMode: choreographer.immersionMode,
|
||||
controller: this,
|
||||
);
|
||||
_toolbarDisplayControllers[eventId]!.setToolbar();
|
||||
} catch (e, s) {
|
||||
ErrorHandler.logError(
|
||||
e: e,
|
||||
s: s,
|
||||
m: "Failed to set toolbar display controller",
|
||||
data: {
|
||||
"eventId": eventId,
|
||||
"event": event.toJson(),
|
||||
"pangeaMessageEvent": _pangeaMessageEvents[eventId]?.toString(),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
PangeaMessageEvent? getPangeaMessageEvent(String eventId) {
|
||||
|
|
|
|||
|
|
@ -256,7 +256,10 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
// #Pangea
|
||||
case SpaceChildContextAction.archive:
|
||||
widget.controller.cancelAction();
|
||||
widget.controller.toggleSelection(room!.id);
|
||||
// #Pangea
|
||||
if (room == null) return;
|
||||
// Pangea#
|
||||
widget.controller.toggleSelection(room.id);
|
||||
room.isSpace
|
||||
? await showFutureLoadingDialog(
|
||||
context: context,
|
||||
|
|
@ -273,7 +276,10 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
break;
|
||||
case SpaceChildContextAction.addToSpace:
|
||||
widget.controller.cancelAction();
|
||||
widget.controller.toggleSelection(room!.id);
|
||||
// #Pangea
|
||||
if (room == null) return;
|
||||
// Pangea#
|
||||
widget.controller.toggleSelection(room.id);
|
||||
await widget.controller.addToSpace();
|
||||
break;
|
||||
// Pangea#
|
||||
|
|
|
|||
|
|
@ -119,7 +119,6 @@ class HomeserverPickerController extends State<HomeserverPicker> {
|
|||
// #Pangea
|
||||
// void ssoLoginAction(String id) async {
|
||||
void ssoLoginAction(IdentityProvider provider) async {
|
||||
final id = provider.id!;
|
||||
//Pangea#
|
||||
final redirectUrl = kIsWeb
|
||||
// #Pangea
|
||||
|
|
@ -131,7 +130,11 @@ class HomeserverPickerController extends State<HomeserverPicker> {
|
|||
: '${AppConfig.appOpenUrlScheme.toLowerCase()}://login';
|
||||
//Pangea#
|
||||
final url = Matrix.of(context).getLoginClient().homeserver!.replace(
|
||||
path: '/_matrix/client/v3/login/sso/redirect${id == null ? '' : '/$id'}',
|
||||
// #Pangea
|
||||
// path: '/_matrix/client/v3/login/sso/redirect${id == null ? '' : '/$id'}',
|
||||
path:
|
||||
'/_matrix/client/v3/login/sso/redirect${provider.id == null ? '' : '/${provider.id}'}',
|
||||
// Pangea#
|
||||
queryParameters: {'redirectUrl': redirectUrl},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -192,8 +192,6 @@ class NewSpaceController extends State<NewSpace> {
|
|||
// Pangea#
|
||||
);
|
||||
// #Pangea
|
||||
Room? room = Matrix.of(context).client.getRoomById(spaceId);
|
||||
|
||||
final List<Future<dynamic>> futures = [
|
||||
Matrix.of(context).client.waitForRoomInSync(spaceId, join: true),
|
||||
];
|
||||
|
|
@ -202,8 +200,6 @@ class NewSpaceController extends State<NewSpace> {
|
|||
}
|
||||
await Future.wait(futures);
|
||||
|
||||
room = Matrix.of(context).client.getRoomById(spaceId);
|
||||
|
||||
final newChatRoomId = await Matrix.of(context).client.createGroupChat(
|
||||
enableEncryption: false,
|
||||
preset: sdk.CreateRoomPreset.publicChat,
|
||||
|
|
@ -212,7 +208,18 @@ class NewSpaceController extends State<NewSpace> {
|
|||
);
|
||||
GoogleAnalytics.createChat(newChatRoomId);
|
||||
|
||||
room!.setSpaceChild(newChatRoomId, suggested: true);
|
||||
final Room? room = Matrix.of(context).client.getRoomById(spaceId);
|
||||
if (room == null) {
|
||||
ErrorHandler.logError(
|
||||
e: 'Failed to get new space by id $spaceId',
|
||||
);
|
||||
MatrixState.pangeaController.classController
|
||||
.setActiveSpaceIdInChatListController(spaceId);
|
||||
context.push('/spaces/$spaceId');
|
||||
return;
|
||||
}
|
||||
|
||||
room.setSpaceChild(newChatRoomId, suggested: true);
|
||||
newClassMode
|
||||
? GoogleAnalytics.addParent(
|
||||
newChatRoomId,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
|
|||
import 'package:fluffychat/pangea/models/class_model.dart';
|
||||
import 'package:fluffychat/pangea/models/it_step.dart';
|
||||
import 'package:fluffychat/pangea/models/message_data_models.dart';
|
||||
import 'package:fluffychat/pangea/models/widget_measurement.dart';
|
||||
import 'package:fluffychat/pangea/utils/any_state_holder.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/utils/overlay.dart';
|
||||
|
|
@ -136,7 +135,7 @@ class Choreographer {
|
|||
|
||||
_resetDebounceTimer() {
|
||||
if (debounceTimer != null) {
|
||||
debounceTimer!.cancel();
|
||||
debounceTimer?.cancel();
|
||||
debounceTimer = null;
|
||||
}
|
||||
}
|
||||
|
|
@ -252,6 +251,7 @@ class Choreographer {
|
|||
s: StackTrace.current,
|
||||
);
|
||||
MatrixState.pAnyState.closeOverlay();
|
||||
return;
|
||||
}
|
||||
if (igc.igcTextData!.matches[matchIndex].match.choices == null) {
|
||||
ErrorHandler.logError(
|
||||
|
|
@ -259,6 +259,7 @@ class Choreographer {
|
|||
s: StackTrace.current,
|
||||
);
|
||||
MatrixState.pAnyState.closeOverlay();
|
||||
return;
|
||||
}
|
||||
|
||||
//if it's the wrong choice, return
|
||||
|
|
@ -478,8 +479,6 @@ class Choreographer {
|
|||
}
|
||||
}
|
||||
|
||||
WidgetMeasurements get inputBarSize => _textController.measurements!;
|
||||
|
||||
bool get showIsError => !itController.isOpen && errorService.isError;
|
||||
|
||||
LayerLinkAndKey get itBarLinkAndKey =>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/controllers/error_service.dart';
|
||||
import 'package:fluffychat/pangea/models/igc_text_data_model.dart';
|
||||
|
|
@ -13,6 +8,10 @@ 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';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
||||
|
||||
import '../../../widgets/matrix.dart';
|
||||
import '../../models/language_detection_model.dart';
|
||||
import '../../models/span_card_model.dart';
|
||||
|
|
@ -136,6 +135,21 @@ class IgcController {
|
|||
data: igcTextData!.toJson(),
|
||||
);
|
||||
}
|
||||
|
||||
if (choreographer.l1LangCode == null ||
|
||||
choreographer.l2LangCode == null) {
|
||||
debugger(when: kDebugMode);
|
||||
ErrorHandler.logError(
|
||||
m: "l1LangCode and/or l2LangCode is null",
|
||||
s: StackTrace.current,
|
||||
data: {
|
||||
"l1LangCode": choreographer.l1LangCode,
|
||||
"l2LangCode": choreographer.l2LangCode,
|
||||
},
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
final TokensResponseModel res = await TokensRepo.tokenize(
|
||||
await choreographer.pangeaController.userController.accessToken,
|
||||
TokensRequestModel(
|
||||
|
|
@ -155,7 +169,7 @@ class IgcController {
|
|||
);
|
||||
ErrorHandler.logError(e: err, s: stack);
|
||||
} finally {
|
||||
igcTextData!.loading = false;
|
||||
igcTextData?.loading = false;
|
||||
choreographer.stopLoading();
|
||||
}
|
||||
}
|
||||
|
|
@ -184,7 +198,7 @@ class IgcController {
|
|||
cursorOffset: match.match.offset,
|
||||
),
|
||||
onITStart: () {
|
||||
if (choreographer.itEnabled) {
|
||||
if (choreographer.itEnabled && igcTextData != null) {
|
||||
choreographer.onITStart(igcTextData!.matches[firstMatchIndex]);
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -119,7 +119,6 @@ class ITController {
|
|||
choreographer.startLoading();
|
||||
|
||||
final String currentText = choreographer.currentText;
|
||||
final String? translationId = currentITStep?.translationId;
|
||||
|
||||
if (sourceText == null) await _setSourceText();
|
||||
|
||||
|
|
@ -264,6 +263,7 @@ class ITController {
|
|||
|
||||
//maybe we store IT data in the same format? make a specific kind of match?
|
||||
void selectTranslation(int chosenIndex) {
|
||||
if (currentITStep == null) return;
|
||||
final itStep = ITStep(currentITStep!.continuances, chosen: chosenIndex);
|
||||
|
||||
completedITSteps.add(itStep);
|
||||
|
|
|
|||
|
|
@ -225,6 +225,13 @@ class ITChoices extends StatelessWidget {
|
|||
Color? borderColor,
|
||||
String? choiceFeedback,
|
||||
]) {
|
||||
if (controller.currentITStep == null) {
|
||||
ErrorHandler.logError(
|
||||
m: "currentITStep is null in showCard",
|
||||
s: StackTrace.current,
|
||||
);
|
||||
return;
|
||||
}
|
||||
OverlayUtil.showPositionedCard(
|
||||
context: context,
|
||||
cardToShow: choiceFeedback == null
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:fluffychat/pangea/repo/full_text_translation_repo.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/widgets/igc/why_button.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:http/http.dart';
|
||||
|
|
@ -62,6 +63,12 @@ class ITFeedbackCardController extends State<ITFeedbackCard> {
|
|||
}
|
||||
|
||||
Future<void> translateFeedback() async {
|
||||
if (res == null) {
|
||||
ErrorHandler.logError(
|
||||
m: "Cannot translate feedback because res is null",
|
||||
);
|
||||
return;
|
||||
}
|
||||
setState(() {
|
||||
isTranslating = true;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,17 +1,16 @@
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart';
|
||||
import 'package:fluffychat/pangea/models/class_model.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import '../../../widgets/matrix.dart';
|
||||
|
||||
class _ErrorCopy {
|
||||
|
|
@ -72,6 +71,12 @@ class LanguagePermissionsButtons extends StatelessWidget {
|
|||
_ErrorCopy? getCopy(BuildContext context) {
|
||||
final bool itDisabled = !choreographer.itEnabled;
|
||||
final bool igcDisabled = !choreographer.igcEnabled;
|
||||
if (roomID == null) {
|
||||
ErrorHandler.logError(
|
||||
e: Exception("Room ID is null in language permissions"),
|
||||
);
|
||||
return null;
|
||||
}
|
||||
final Room? room = Matrix.of(context).client.getRoomById(roomID!);
|
||||
|
||||
final bool itDisabledByClass = choreographer
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@ class ModelKey {
|
|||
static const String offset = "offset";
|
||||
static const String length = "length";
|
||||
static const String langCode = 'lang_code';
|
||||
// some old analytics rooms have langCode instead of lang_code in the room creation content
|
||||
static const String oldLangCode = 'langCode';
|
||||
static const String wordLang = "word_lang";
|
||||
static const String lemma = "lemma";
|
||||
static const String saveVocab = "save_vocab";
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/enum/construct_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/enum/time_span.dart';
|
||||
import 'package:fluffychat/pangea/models/headwords.dart';
|
||||
import 'package:fluffychat/pangea/models/student_analytics_summary_model.dart';
|
||||
import 'package:fluffychat/pangea/pages/analytics/base_analytics_page.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import '../constants/class_default_values.dart';
|
||||
import '../extensions/client_extension.dart';
|
||||
import '../extensions/pangea_room_extension.dart';
|
||||
|
|
@ -264,7 +263,17 @@ class AnalyticsController extends BaseController {
|
|||
) {
|
||||
final Room? analyticsRoom = _pangeaController.matrixState.client
|
||||
.analyticsRoomLocal(langCode, studentId);
|
||||
return analyticsRoom!.allConstructEvents;
|
||||
if (analyticsRoom == null) {
|
||||
ErrorHandler.logError(
|
||||
m: "analyticsRoom missing in studentConstructs",
|
||||
s: StackTrace.current,
|
||||
data: {
|
||||
"studentId": studentId,
|
||||
"langCode": langCode,
|
||||
},
|
||||
);
|
||||
}
|
||||
return analyticsRoom?.allConstructEvents ?? Future.value([]);
|
||||
}
|
||||
|
||||
Future<List<ConstructEvent>> spaceMemberVocab(String spaceId) async {
|
||||
|
|
@ -309,25 +318,24 @@ class AnalyticsController extends BaseController {
|
|||
// as long as a student isn't selected, we want the vocab events for the whole class
|
||||
final Room? classRoom =
|
||||
_pangeaController.matrixState.client.getRoomById(defaultSelected.id);
|
||||
if (classRoom == null) {
|
||||
if (classRoom?.classSettings == null) {
|
||||
throw Exception("classRoom missing in spaceMemberVocab");
|
||||
}
|
||||
langCode = classRoom.classSettings!.targetLanguage;
|
||||
|
||||
if (selected?.type != AnalyticsEntryType.student) {
|
||||
eventsFuture = spaceMemberVocab(defaultSelected.id);
|
||||
} else {
|
||||
eventsFuture = studentConstructs(selected!.id, langCode);
|
||||
}
|
||||
langCode = classRoom!.classSettings!.targetLanguage;
|
||||
eventsFuture = selected?.type == AnalyticsEntryType.student
|
||||
? studentConstructs(selected!.id, langCode)
|
||||
: spaceMemberVocab(defaultSelected.id);
|
||||
} else if (defaultSelected.type == AnalyticsEntryType.student) {
|
||||
// in this case, we're on an individual's own analytics page
|
||||
|
||||
if (selected?.type == AnalyticsEntryType.space ||
|
||||
selected?.type == AnalyticsEntryType.student) {
|
||||
langCode = _pangeaController.languageController
|
||||
.activeL2Code(roomID: selected!.id)!;
|
||||
eventsFuture = myConstructs(langCode);
|
||||
} else {
|
||||
if (_pangeaController.languageController.userL2 == null) {
|
||||
throw Exception("userL2 missing in vocabHeadsByAnalyticsSelected");
|
||||
}
|
||||
langCode = _pangeaController.languageController.userL2!.langCode;
|
||||
eventsFuture = myConstructs(langCode);
|
||||
}
|
||||
|
|
@ -361,11 +369,9 @@ class AnalyticsController extends BaseController {
|
|||
throw "No target language available";
|
||||
}
|
||||
|
||||
if (selected?.type != AnalyticsEntryType.student) {
|
||||
eventFutures = spaceMemberVocab(defaultSelected.id);
|
||||
} else {
|
||||
eventFutures = studentConstructs(selected!.id, langCode);
|
||||
}
|
||||
eventFutures = selected?.type == AnalyticsEntryType.student
|
||||
? studentConstructs(selected!.id, langCode)
|
||||
: spaceMemberVocab(defaultSelected.id);
|
||||
} else if (defaultSelected.type == AnalyticsEntryType.student) {
|
||||
// in this case, we're on an individual's own analytics page
|
||||
|
||||
|
|
@ -375,6 +381,9 @@ class AnalyticsController extends BaseController {
|
|||
.activeL2Code(roomID: selected!.id)!;
|
||||
eventFutures = myConstructs(langCode);
|
||||
} else {
|
||||
if (_pangeaController.languageController.userL2 == null) {
|
||||
throw "userL2 missing in constuctEventsByAnalyticsSelected";
|
||||
}
|
||||
langCode = _pangeaController.languageController.userL2!.langCode;
|
||||
eventFutures = myConstructs(langCode);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/controllers/pangea_controller.dart';
|
||||
import 'package:fluffychat/pangea/models/student_analytics_summary_model.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import '../extensions/client_extension.dart';
|
||||
import '../extensions/pangea_room_extension.dart';
|
||||
import '../models/constructs_analytics_model.dart';
|
||||
|
|
@ -62,8 +61,10 @@ class MyAnalyticsController {
|
|||
List<Room> spaces,
|
||||
) async {
|
||||
final List<Future<StudentAnalyticsEvent?>> events = [];
|
||||
for (final space in spaces) {
|
||||
events.add(space.getStudentAnalytics(_userId!));
|
||||
if (_userId != null) {
|
||||
for (final space in spaces) {
|
||||
events.add(space.getStudentAnalytics(_userId!));
|
||||
}
|
||||
}
|
||||
return Future.wait(events);
|
||||
}
|
||||
|
|
@ -80,6 +81,7 @@ class MyAnalyticsController {
|
|||
try {
|
||||
final Map<String, List<OneConstructUse>> aggregatedVocabUse = {};
|
||||
for (final use in allUses) {
|
||||
if (use.lemma == null) continue;
|
||||
aggregatedVocabUse[use.lemma!] ??= [];
|
||||
aggregatedVocabUse[use.lemma]!.add(use);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,8 +116,6 @@ class PangeaController {
|
|||
|
||||
matrixState.loginHomeserverSummary =
|
||||
await matrixState.getLoginClient().checkHomeserver(homeserver);
|
||||
final ssoSupported = matrixState.loginHomeserverSummary!.loginFlows
|
||||
.any((flow) => flow.type == 'm.login.sso');
|
||||
|
||||
try {
|
||||
await matrixState.getLoginClient().register();
|
||||
|
|
|
|||
|
|
@ -169,6 +169,13 @@ class SubscriptionController extends BaseController {
|
|||
}
|
||||
|
||||
void setNewUserTrial() {
|
||||
if (_pangeaController.userController.userModel?.profile == null) {
|
||||
ErrorHandler.logError(
|
||||
m: "Null user profile in subscription settings",
|
||||
s: StackTrace.current,
|
||||
);
|
||||
return;
|
||||
}
|
||||
final String profileCreatedAt =
|
||||
_pangeaController.userController.userModel!.profile!.createdAt;
|
||||
final DateTime creationTimestamp = DateTime.parse(profileCreatedAt);
|
||||
|
|
|
|||
|
|
@ -2,14 +2,15 @@ import 'dart:async';
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:jwt_decode/jwt_decode.dart';
|
||||
import 'package:matrix/matrix.dart' as matrix;
|
||||
|
||||
import 'package:fluffychat/pangea/constants/language_keys.dart';
|
||||
import 'package:fluffychat/pangea/constants/model_keys.dart';
|
||||
import 'package:fluffychat/pangea/controllers/base_controller.dart';
|
||||
import 'package:fluffychat/pangea/controllers/pangea_controller.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:fluffychat/widgets/fluffy_chat_app.dart';
|
||||
import 'package:jwt_decode/jwt_decode.dart';
|
||||
import 'package:matrix/matrix.dart' as matrix;
|
||||
|
||||
import '../constants/local.key.dart';
|
||||
import '../models/user_model.dart';
|
||||
import '../repo/user_repo.dart';
|
||||
|
|
@ -148,7 +149,11 @@ class UserController extends BaseController {
|
|||
}
|
||||
|
||||
_savePUserModel(PUserModel? pUserModel) {
|
||||
final jsonUser = pUserModel!.toJson();
|
||||
if (pUserModel == null) {
|
||||
ErrorHandler.logError(e: "trying to save null userModel");
|
||||
return;
|
||||
}
|
||||
final jsonUser = pUserModel.toJson();
|
||||
_pangeaController.pStoreService.save(PLocalKey.user, jsonUser);
|
||||
|
||||
setState(data: pUserModel);
|
||||
|
|
|
|||
|
|
@ -104,7 +104,6 @@ extension PangeaClient on Client {
|
|||
});
|
||||
if (analyticsRoom != null &&
|
||||
analyticsRoom.membership == Membership.invite) {
|
||||
final membership = analyticsRoom.membership;
|
||||
debugger(when: kDebugMode);
|
||||
analyticsRoom
|
||||
.join()
|
||||
|
|
|
|||
|
|
@ -192,6 +192,7 @@ extension PangeaRoom on Room {
|
|||
//a space show up in spaceChildren but the user has not been invited to them.
|
||||
List<String> get childrenAndGrandChildrenDirectChatIds {
|
||||
final List<String> nonDirectChatRoomIds = childrenAndGrandChildren
|
||||
.where((child) => child.roomId != null)
|
||||
.map((e) => client.getRoomById(e.roomId!))
|
||||
.where((r) => r != null && !r.isDirectChat)
|
||||
.map((e) => e!.id)
|
||||
|
|
@ -280,11 +281,11 @@ extension PangeaRoom on Room {
|
|||
bool isMadeByUser(String userId) =>
|
||||
getState(EventTypes.RoomCreate)?.senderId == userId;
|
||||
|
||||
bool isMadeForLang(String langCode) =>
|
||||
getState(EventTypes.RoomCreate)
|
||||
?.content
|
||||
.tryGet<String>(ModelKey.langCode) ==
|
||||
langCode;
|
||||
bool isMadeForLang(String langCode) {
|
||||
final creationContent = getState(EventTypes.RoomCreate)?.content;
|
||||
return creationContent?.tryGet<String>(ModelKey.langCode) == langCode ||
|
||||
creationContent?.tryGet<String>(ModelKey.oldLangCode) == langCode;
|
||||
}
|
||||
|
||||
bool isAnalyticsRoomOfUser(String userId) =>
|
||||
isAnalyticsRoom && isMadeByUser(userId);
|
||||
|
|
@ -766,6 +767,9 @@ extension PangeaRoom on Room {
|
|||
|
||||
/// update state event and return eventId
|
||||
Future<String> updateStateEvent(Event stateEvent) {
|
||||
if (stateEvent.stateKey == null) {
|
||||
throw Exception("stateEvent.stateKey is null");
|
||||
}
|
||||
return client.setRoomStateWithKey(
|
||||
id,
|
||||
stateEvent.type,
|
||||
|
|
@ -923,7 +927,8 @@ extension PangeaRoom on Room {
|
|||
if (isDirectChat) return false;
|
||||
if (!isSpace) {
|
||||
if (eventsDefaultPowerLevel == null) return null;
|
||||
return eventsDefaultPowerLevel! >= ClassDefaultValues.powerLevelOfAdmin;
|
||||
return (eventsDefaultPowerLevel ?? 0) >=
|
||||
ClassDefaultValues.powerLevelOfAdmin;
|
||||
}
|
||||
for (final child in spaceChildren) {
|
||||
if (child.roomId == null) continue;
|
||||
|
|
|
|||
|
|
@ -709,7 +709,11 @@ class _LanguageLocal {
|
|||
// debugger(when: kDebugMode);
|
||||
// ErrorHandler.logError(m: "Bad language key $key", s: StackTrace.current);
|
||||
}
|
||||
if (item == null) return key;
|
||||
if (item == null ||
|
||||
(native && !item.containsKey("nativeName") ||
|
||||
(!native && !item.containsKey("name")))) {
|
||||
return key;
|
||||
}
|
||||
|
||||
return (native ? item["nativeName"]! : item["name"]!).split(",")[0];
|
||||
}
|
||||
|
|
@ -720,7 +724,8 @@ class _LanguageLocal {
|
|||
|
||||
final String searchName = name.toLowerCase().split(" ")[0];
|
||||
for (final entry in isoLangs.entries) {
|
||||
if (entry.value["name"]!.toLowerCase().contains(searchName)) {
|
||||
if (entry.value.containsKey("name") &&
|
||||
entry.value["name"]!.toLowerCase().contains(searchName)) {
|
||||
return entry.key;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ class RepresentationEvent {
|
|||
|
||||
_tokens = tokenEvents.first.getPangeaContent<PangeaMessageTokens>();
|
||||
|
||||
return _tokens!.tokens;
|
||||
return _tokens?.tokens;
|
||||
}
|
||||
|
||||
Future<List<PangeaToken>?> tokensGlobal(BuildContext context) async {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import 'package:sentry_flutter/sentry_flutter.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/controllers/subscription_controller.dart';
|
||||
import 'package:fluffychat/pangea/models/base_subscription_info.dart';
|
||||
import 'package:fluffychat/pangea/repo/subscription_repo.dart';
|
||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
||||
|
||||
class WebSubscriptionInfo extends SubscriptionInfo {
|
||||
WebSubscriptionInfo({required super.pangeaController}) : super();
|
||||
|
|
@ -12,6 +11,14 @@ class WebSubscriptionInfo extends SubscriptionInfo {
|
|||
await setAppIds();
|
||||
await setAllProducts();
|
||||
await setCustomerInfo();
|
||||
|
||||
if (allProducts == null || appIds == null) {
|
||||
Sentry.addBreadcrumb(
|
||||
Breadcrumb(message: "No products found for current app"),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
availableSubscriptions = allProducts!
|
||||
.where((product) => product.appId == appIds!.currentAppId)
|
||||
.toList();
|
||||
|
|
|
|||
|
|
@ -1,18 +1,17 @@
|
|||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/constants/pangea_event_types.dart';
|
||||
import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
|
||||
import 'package:fluffychat/pangea/models/chart_analytics_model.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/widgets/common/list_placeholder.dart';
|
||||
import 'package:fluffychat/pangea/widgets/common/p_circular_loader.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import '../../../../widgets/matrix.dart';
|
||||
import '../../../controllers/pangea_controller.dart';
|
||||
import '../../../utils/sync_status_util_v2.dart';
|
||||
|
|
@ -41,7 +40,7 @@ class ClassAnalyticsV2Controller extends State<ClassAnalyticsPage> {
|
|||
void initState() {
|
||||
super.initState();
|
||||
Future.delayed(Duration.zero, () async {
|
||||
if (classRoom == null || !classRoom!.isSpace) {
|
||||
if (classRoom == null || (!(classRoom?.isSpace ?? false))) {
|
||||
context.go('/rooms');
|
||||
}
|
||||
stateSub = _pangeaController.matrixState.client.onRoomState.stream
|
||||
|
|
@ -57,16 +56,17 @@ class ClassAnalyticsV2Controller extends State<ClassAnalyticsPage> {
|
|||
|
||||
Future<void> getChatAndStudents() async {
|
||||
try {
|
||||
await classRoom!.requestParticipants();
|
||||
await classRoom?.requestParticipants();
|
||||
|
||||
students = classRoom!.students;
|
||||
|
||||
chats = classRoom!.spaceChildren
|
||||
.where((element) => element.roomId != null)
|
||||
.map((e) => Matrix.of(context).client.getRoomById(e.roomId!))
|
||||
.where((r) => r != null)
|
||||
.cast<Room>()
|
||||
.toList();
|
||||
if (classRoom != null) {
|
||||
students = classRoom!.students;
|
||||
chats = classRoom!.spaceChildren
|
||||
.where((element) => element.roomId != null)
|
||||
.map((e) => Matrix.of(context).client.getRoomById(e.roomId!))
|
||||
.where((r) => r != null)
|
||||
.cast<Room>()
|
||||
.toList();
|
||||
}
|
||||
|
||||
setState(() {
|
||||
_initialized = true;
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:fl_chart/fl_chart.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/pangea/pages/analytics/bar_chart_placeholder_data.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
import '../../enum/time_span.dart';
|
||||
import '../../enum/use_type.dart';
|
||||
import '../../models/chart_analytics_model.dart';
|
||||
|
|
@ -245,11 +244,12 @@ class MessagesBarChartState extends State<MessagesBarChart> {
|
|||
final TimeSeriesInterval? last =
|
||||
intervalGroupings.isNotEmpty ? intervalGroupings.last.last : null;
|
||||
|
||||
if (isInSameGroup(
|
||||
last,
|
||||
timeSeriesInterval,
|
||||
widget.chartAnalytics!.timeSpan,
|
||||
)) {
|
||||
if (widget.chartAnalytics != null &&
|
||||
isInSameGroup(
|
||||
last,
|
||||
timeSeriesInterval,
|
||||
widget.chartAnalytics!.timeSpan,
|
||||
)) {
|
||||
intervalGroupings.last.add(timeSeriesInterval);
|
||||
} else {
|
||||
intervalGroupings.add([timeSeriesInterval]);
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||
|
||||
void showEditFieldDialog(BuildContext context, String title) async {
|
||||
// final room = Matrix.of(context).client.getRoomById(roomId!)!;
|
||||
final input = await showTextInputDialog(
|
||||
useRootNavigator: false,
|
||||
context: context,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/widgets/class/add_class_and_invite.dart';
|
||||
import 'package:fluffychat/pangea/widgets/class/add_space_toggles.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
class AddExchangeToClass extends StatefulWidget {
|
||||
const AddExchangeToClass({super.key});
|
||||
|
|
@ -19,8 +17,12 @@ class AddExchangeToClassState extends State<AddExchangeToClass> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final String spaceId =
|
||||
GoRouterState.of(context).pathParameters['exchangeid']!;
|
||||
final String? spaceId =
|
||||
GoRouterState.of(context).pathParameters['exchangeid'];
|
||||
if (spaceId == null) {
|
||||
return const SizedBox();
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ class SubscriptionManagementController extends State<SubscriptionManagement> {
|
|||
managementUrl += "?prefilled_email=${Uri.encodeComponent(email)}";
|
||||
}
|
||||
final String? purchaseAppId =
|
||||
subscriptionController.subscription?.currentSubscription?.appId!;
|
||||
subscriptionController.subscription?.currentSubscription?.appId;
|
||||
if (purchaseAppId == null) return;
|
||||
|
||||
final SubscriptionAppIds? appIds =
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/pages/sign_up/signup_view.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/utils/firebase_analytics.dart';
|
||||
import 'package:fluffychat/utils/localized_exception_extension.dart';
|
||||
import 'package:fluffychat/utils/platform_infos.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
|
||||
class SignupPage extends StatefulWidget {
|
||||
const SignupPage({super.key});
|
||||
|
|
@ -133,7 +131,7 @@ class SignupPageController extends State<SignupPage> {
|
|||
//Pangea#
|
||||
|
||||
// Set displayname
|
||||
if (displayname != localPart) {
|
||||
if (displayname != localPart && client.userID != null) {
|
||||
await client.setDisplayName(
|
||||
client.userID!,
|
||||
displayname,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:http/http.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/config/environment.dart';
|
||||
import 'package:fluffychat/pangea/enum/span_choice_type.dart';
|
||||
import 'package:fluffychat/pangea/enum/span_data_type.dart';
|
||||
import 'package:fluffychat/pangea/models/span_data.dart';
|
||||
import 'package:http/http.dart';
|
||||
|
||||
import '../constants/model_keys.dart';
|
||||
import '../network/requests.dart';
|
||||
import '../network/urls.dart';
|
||||
|
|
@ -31,15 +31,15 @@ class SpanDataRepo {
|
|||
}
|
||||
}
|
||||
|
||||
Future<SpanDetailsRepoReqAndRes> getMock(SpanDetailsRepoReqAndRes req) async {
|
||||
await Future.delayed(const Duration(seconds: 2));
|
||||
if (req.span.choices != null &&
|
||||
req.span.choices!.any((element) => element.selected)) {
|
||||
return req..span = mockReponseWithHintOne.span;
|
||||
} else {
|
||||
return req..span = mockReponseWithChoices.span;
|
||||
}
|
||||
}
|
||||
// Future<SpanDetailsRepoReqAndRes> getMock(SpanDetailsRepoReqAndRes req) async {
|
||||
// await Future.delayed(const Duration(seconds: 2));
|
||||
// if (req.span.choices != null &&
|
||||
// req.span.choices!.any((element) => element.selected)) {
|
||||
// return req..span = mockReponseWithHintOne.span;
|
||||
// } else {
|
||||
// return req..span = mockReponseWithChoices.span;
|
||||
// }
|
||||
// }
|
||||
|
||||
class SpanDetailsRepoReqAndRes {
|
||||
String userL1;
|
||||
|
|
@ -105,9 +105,9 @@ SpanDetailsRepoReqAndRes get mockReponseWithChoices {
|
|||
return res;
|
||||
}
|
||||
|
||||
SpanDetailsRepoReqAndRes get mockReponseWithHintOne {
|
||||
final SpanDetailsRepoReqAndRes res = mockReponseWithChoices;
|
||||
res.span.choices![1].selected = true;
|
||||
res.span.message = "Conjugation error";
|
||||
return res;
|
||||
}
|
||||
// SpanDetailsRepoReqAndRes get mockReponseWithHintOne {
|
||||
// final SpanDetailsRepoReqAndRes res = mockReponseWithChoices;
|
||||
// res.span.choices![1].selected = true;
|
||||
// res.span.message = "Conjugation error";
|
||||
// return res;
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'package:firebase_analytics/firebase_analytics.dart';
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/controllers/subscription_controller.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import '../../config/firebase_options.dart';
|
||||
import '../enum/use_type.dart';
|
||||
|
||||
|
|
@ -161,22 +160,26 @@ class GoogleAnalytics {
|
|||
);
|
||||
}
|
||||
|
||||
static FirebaseAnalyticsObserver getAnalyticsObserver() =>
|
||||
FirebaseAnalyticsObserver(
|
||||
analytics: analytics!,
|
||||
routeFilter: (route) {
|
||||
// By default firebase only tracks page routes
|
||||
if (route is! PageRoute ||
|
||||
// No user logged in, so we dont track
|
||||
route.settings.name == "login" ||
|
||||
route.settings.name == "/home" ||
|
||||
route.settings.name == "connect" ||
|
||||
route.settings.name == "signup") {
|
||||
return false;
|
||||
}
|
||||
final String? name = route.settings.name;
|
||||
debugPrint("navigating to route: $name");
|
||||
return true;
|
||||
},
|
||||
);
|
||||
static FirebaseAnalyticsObserver getAnalyticsObserver() {
|
||||
if (analytics == null) {
|
||||
throw Exception("Firebase Analytics not initialized");
|
||||
}
|
||||
return FirebaseAnalyticsObserver(
|
||||
analytics: analytics!,
|
||||
routeFilter: (route) {
|
||||
// By default firebase only tracks page routes
|
||||
if (route is! PageRoute ||
|
||||
// No user logged in, so we dont track
|
||||
route.settings.name == "login" ||
|
||||
route.settings.name == "/home" ||
|
||||
route.settings.name == "connect" ||
|
||||
route.settings.name == "signup") {
|
||||
return false;
|
||||
}
|
||||
final String? name = route.settings.name;
|
||||
debugPrint("navigating to route: $name");
|
||||
return true;
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,49 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
|
||||
// Used in lock space. Handles case when child rooms return null from client.getRoomById
|
||||
// Because the user hasn't joined them
|
||||
Future<List<Room>> joinAllSpaceChats(Room space, Client client) async {
|
||||
final List<String> childrenIds =
|
||||
space.spaceChildren.map((x) => x.roomId!).toList();
|
||||
|
||||
final List<Room> children = [];
|
||||
for (final String childId in childrenIds) {
|
||||
final Room? child = client.getRoomById(childId);
|
||||
if (child != null) {
|
||||
children.add(child);
|
||||
}
|
||||
// child may be null if the user is not in the room
|
||||
else {
|
||||
final Room? child = await tryGetRoomById(childId, client);
|
||||
if (child != null) {
|
||||
children.add(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
Future<Room?> tryGetRoomById(String roomId, Client client) async {
|
||||
try {
|
||||
await client.joinRoomById(roomId);
|
||||
} catch (err) {
|
||||
// caused when chat has been archived
|
||||
debugPrint("Failed to join $roomId");
|
||||
return null;
|
||||
}
|
||||
await client.waitForRoomInSync(roomId);
|
||||
final Room? room = client.getRoomById(roomId);
|
||||
if (room != null) {
|
||||
return room;
|
||||
} else {
|
||||
ErrorHandler.logError(
|
||||
e: "Failed to fetch child room with id $roomId after joining",
|
||||
s: StackTrace.current,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -49,6 +49,7 @@ Future<void> unlockChat(Room room, Client client) async {
|
|||
|
||||
Future<void> lockSpace(Room space, Client client) async {
|
||||
for (final spaceChild in space.spaceChildren) {
|
||||
if (spaceChild.roomId == null) continue;
|
||||
Room? child = client.getRoomById(spaceChild.roomId!);
|
||||
if (child == null) {
|
||||
try {
|
||||
|
|
@ -70,6 +71,7 @@ Future<void> lockSpace(Room space, Client client) async {
|
|||
|
||||
Future<void> unlockSpace(Room space, Client client) async {
|
||||
for (final spaceChild in space.spaceChildren) {
|
||||
if (spaceChild.roomId == null) continue;
|
||||
final Room? child = client.getRoomById(spaceChild.roomId!);
|
||||
if (child == null) continue;
|
||||
child.isSpace
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import '../../utils/matrix_sdk_extensions/matrix_locals.dart';
|
||||
|
||||
void setClassDisplayname(BuildContext context, String? roomId) async {
|
||||
final room = Matrix.of(context).client.getRoomById(roomId!)!;
|
||||
if (roomId == null) return;
|
||||
final room = Matrix.of(context).client.getRoomById(roomId);
|
||||
if (room == null) return;
|
||||
final TextEditingController textFieldController = TextEditingController(
|
||||
text: room.getLocalizedDisplayname(
|
||||
MatrixLocals(
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ class ToolbarDisplayController {
|
|||
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
Widget overlayEntry;
|
||||
if (toolbar == null) return;
|
||||
try {
|
||||
overlayEntry = Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
|
||||
import '../../../widgets/matrix.dart';
|
||||
import '../../utils/error_handler.dart';
|
||||
import '../../utils/firebase_analytics.dart';
|
||||
|
|
@ -92,7 +91,7 @@ class AddToClassAndInviteState extends State<AddToClassAndInviteToggles> {
|
|||
Future<void> _addSingleParent(String roomToAddId, Room newParent) async {
|
||||
GoogleAnalytics.addParent(roomToAddId, newParent.classCode);
|
||||
final List<List<User>> existingMembers = await Future.wait([
|
||||
room!.requestParticipants(),
|
||||
room?.requestParticipants() ?? Future.value([]),
|
||||
newParent.requestParticipants(),
|
||||
]);
|
||||
final List<User> roomMembers = existingMembers[0];
|
||||
|
|
@ -102,7 +101,7 @@ class AddToClassAndInviteState extends State<AddToClassAndInviteToggles> {
|
|||
newParent.setSpaceChild(roomToAddId, suggested: true),
|
||||
];
|
||||
for (final spaceMember
|
||||
in spaceMembers.where((element) => element.id != room!.client.userID)) {
|
||||
in spaceMembers.where((element) => element.id != room?.client.userID)) {
|
||||
if (!roomMembers.any(
|
||||
(m) => m.id == spaceMember.id && m.membership == Membership.join,
|
||||
)) {
|
||||
|
|
@ -118,7 +117,7 @@ class AddToClassAndInviteState extends State<AddToClassAndInviteToggles> {
|
|||
//function for kicking single student and haandling error
|
||||
Future<void> _kickSpaceMember(User spaceMember) async {
|
||||
try {
|
||||
await room!.kick(spaceMember.id);
|
||||
await room?.kick(spaceMember.id);
|
||||
debugPrint('Kicked ${spaceMember.id}');
|
||||
} catch (e) {
|
||||
debugger(when: kDebugMode);
|
||||
|
|
@ -129,7 +128,7 @@ class AddToClassAndInviteState extends State<AddToClassAndInviteToggles> {
|
|||
//function for adding single student and haandling error
|
||||
Future<void> _inviteSpaceMember(User spaceMember) async {
|
||||
try {
|
||||
await room!.invite(spaceMember.id);
|
||||
await room?.invite(spaceMember.id);
|
||||
debugPrint('added ${spaceMember.id}');
|
||||
} catch (e) {
|
||||
debugger(when: kDebugMode);
|
||||
|
|
@ -153,14 +152,14 @@ class AddToClassAndInviteState extends State<AddToClassAndInviteToggles> {
|
|||
return;
|
||||
}
|
||||
final List<List<User>> roomsMembers = await Future.wait([
|
||||
room!.requestParticipants(),
|
||||
room?.requestParticipants() ?? Future.value([]),
|
||||
spaceToRemove.requestParticipants(),
|
||||
]);
|
||||
|
||||
final List<User> toKick = roomsMembers[1]
|
||||
.where(
|
||||
(element) =>
|
||||
element.id != room!.client.userID &&
|
||||
element.id != room?.client.userID &&
|
||||
roomsMembers[0].any((m) => m.id == element.id),
|
||||
)
|
||||
.toList();
|
||||
|
|
@ -176,9 +175,11 @@ class AddToClassAndInviteState extends State<AddToClassAndInviteToggles> {
|
|||
// if (widget.setParentState != null) {
|
||||
// widget.setParentState!();
|
||||
// }
|
||||
await room!.requestParticipants();
|
||||
await room?.requestParticipants();
|
||||
|
||||
GoogleAnalytics.kickClassFromExchange(room!.id, spaceToRemove.id);
|
||||
if (room != null) {
|
||||
GoogleAnalytics.kickClassFromExchange(room!.id, spaceToRemove.id);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart';
|
||||
import 'package:fluffychat/pangea/utils/bot_style.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/widgets/common/bot_face_svg.dart';
|
||||
import 'package:fluffychat/pangea/widgets/igc/card_header.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CardErrorWidget extends StatelessWidget {
|
||||
final Object? error;
|
||||
|
|
@ -28,11 +27,9 @@ class CardErrorWidget extends StatelessWidget {
|
|||
CardHeader(
|
||||
text: errorCopy.title,
|
||||
botExpression: BotExpression.addled,
|
||||
onClose: () => choreographer != null
|
||||
? choreographer!.onMatchError(
|
||||
cursorOffset: offset,
|
||||
)
|
||||
: null,
|
||||
onClose: () => choreographer?.onMatchError(
|
||||
cursorOffset: offset,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
Center(
|
||||
|
|
|
|||
|
|
@ -66,20 +66,26 @@ class SpanCardState extends State<SpanCard> {
|
|||
Future<void> getSpanDetails() async {
|
||||
try {
|
||||
if (widget.scm.pangeaMatch?.isITStart ?? false) return;
|
||||
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
fetchingData = true;
|
||||
});
|
||||
|
||||
await widget.scm.choreographer.igc.getSpanDetails(widget.scm.matchIndex);
|
||||
|
||||
setState(() => fetchingData = false);
|
||||
if (mounted) {
|
||||
setState(() => fetchingData = false);
|
||||
}
|
||||
} catch (e) {
|
||||
// debugger(when: kDebugMode);
|
||||
ErrorHandler.logError(e: e, s: StackTrace.current);
|
||||
setState(() {
|
||||
error = e;
|
||||
fetchingData = false;
|
||||
});
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
error = e;
|
||||
fetchingData = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -105,10 +111,10 @@ class WordMatchContent extends StatelessWidget {
|
|||
.scm
|
||||
.choreographer
|
||||
.igc
|
||||
.igcTextData!
|
||||
.matches[controller.widget.scm.matchIndex]
|
||||
.igcTextData
|
||||
?.matches[controller.widget.scm.matchIndex]
|
||||
.match
|
||||
.choices![index]
|
||||
.choices?[index]
|
||||
.selected = true;
|
||||
|
||||
controller.setState(() => ());
|
||||
|
|
@ -291,6 +297,10 @@ class PromptAndFeedback extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (controller.widget.scm.pangeaMatch == null) {
|
||||
return const SizedBox();
|
||||
}
|
||||
|
||||
return Container(
|
||||
constraints: controller.widget.scm.pangeaMatch!.isITStart
|
||||
? null
|
||||
|
|
|
|||
|
|
@ -190,7 +190,10 @@ class WordDataCardView extends StatelessWidget {
|
|||
style: BotStyle.text(context),
|
||||
),
|
||||
const SizedBox(height: 5.0),
|
||||
if (controller.wordData != null && controller.wordNetError == null)
|
||||
if (controller.wordData != null &&
|
||||
controller.wordNetError == null &&
|
||||
controller.activeL1 != null &&
|
||||
controller.activeL2 != null)
|
||||
WordNetInfo(
|
||||
wordData: controller.wordData!,
|
||||
activeL1: controller.activeL1!,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue