From 64c502b6fa3438ac8c7e8f850301fae534997f22 Mon Sep 17 00:00:00 2001 From: Gabby Gurdin Date: Mon, 18 Mar 2024 11:08:38 -0400 Subject: [PATCH] temp fix for iOS database build errors --- .../pages/analytics/base_analytics.dart | 177 ++++++++++++++ .../pages/analytics/base_analytics_view.dart | 227 ++++++++++++++++++ lib/utils/client_manager.dart | 5 +- .../flutter_matrix_sdk_database_builder.dart | 42 ++-- 4 files changed, 427 insertions(+), 24 deletions(-) create mode 100644 lib/pangea/pages/analytics/base_analytics.dart create mode 100644 lib/pangea/pages/analytics/base_analytics_view.dart diff --git a/lib/pangea/pages/analytics/base_analytics.dart b/lib/pangea/pages/analytics/base_analytics.dart new file mode 100644 index 000000000..32f17ca0b --- /dev/null +++ b/lib/pangea/pages/analytics/base_analytics.dart @@ -0,0 +1,177 @@ +import 'dart:async'; + +import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; +import 'package:fluffychat/pangea/pages/analytics/base_analytics_view.dart'; +import 'package:fluffychat/pangea/pages/analytics/student_analytics/student_analytics.dart'; +import 'package:flutter/material.dart'; +import 'package:matrix/matrix.dart'; + +import '../../../widgets/matrix.dart'; +import '../../controllers/pangea_controller.dart'; +import '../../enum/bar_chart_view_enum.dart'; +import '../../enum/time_span.dart'; +import '../../models/chart_analytics_model.dart'; + +class BaseAnalyticsPage extends StatefulWidget { + final String pageTitle; + final List tabs; + final Future Function(BuildContext) refreshData; + + final AnalyticsSelected defaultSelected; + final AnalyticsSelected? alwaysSelected; + final StudentAnalyticsController? myAnalyticsController; + + const BaseAnalyticsPage({ + super.key, + required this.pageTitle, + required this.tabs, + required this.refreshData, + required this.alwaysSelected, + required this.defaultSelected, + this.myAnalyticsController, + }); + + @override + State createState() => BaseAnalyticsController(); +} + +class BaseAnalyticsController extends State { + final PangeaController pangeaController = MatrixState.pangeaController; + BarChartViewSelection selectedView = BarChartViewSelection.grammar; + AnalyticsSelected? selected; + String? currentLemma; + + bool isSelected(String chatOrStudentId) => chatOrStudentId == selected?.id; + + ChartAnalyticsModel? chartData( + BuildContext context, + AnalyticsSelected? selectedParam, + ) { + final AnalyticsSelected analyticsSelected = + selectedParam ?? widget.defaultSelected; + + if (analyticsSelected.type == AnalyticsEntryType.privateChats) { + return pangeaController.analytics.getAnalyticsLocal( + classId: analyticsSelected.id, + chatId: AnalyticsEntryType.privateChats.toString(), + ); + } + + String? chatId = analyticsSelected.type == AnalyticsEntryType.room + ? analyticsSelected.id + : null; + chatId ??= widget.alwaysSelected?.type == AnalyticsEntryType.room + ? widget.alwaysSelected?.id + : null; + + String? studentId = analyticsSelected.type == AnalyticsEntryType.student + ? analyticsSelected.id + : null; + studentId ??= widget.alwaysSelected?.type == AnalyticsEntryType.student + ? widget.alwaysSelected?.id + : null; + + String? classId = analyticsSelected.type == AnalyticsEntryType.space + ? analyticsSelected.id + : null; + classId ??= widget.alwaysSelected?.type == AnalyticsEntryType.space + ? widget.alwaysSelected?.id + : null; + + final data = pangeaController.analytics.getAnalyticsLocal( + classId: classId, + chatId: chatId, + studentId: studentId, + ); + + return data; + } + + String get barTitle => + "${selectedView.string(context)}: ${selected == null ? widget.defaultSelected.displayName : selected!.displayName}${currentLemma != null ? ' - $currentLemma' : ''}"; + + TimeSpan get currentTimeSpan => + pangeaController.analytics.currentAnalyticsTimeSpan; + + void navigate() { + currentLemma == null + ? Navigator.of(context).pop() + : setState(() => currentLemma = null); + } + + void toggleSelection(AnalyticsSelected selectedParam) { + setState(() { + debugPrint("selectedParam.id is ${selectedParam.id}"); + selected = isSelected(selectedParam.id) ? null : selectedParam; + }); + pangeaController.analytics.setConstructs( + constructType: ConstructType.grammar, + defaultSelected: widget.defaultSelected, + selected: selected, + removeIT: true, + ); + Future.delayed(Duration.zero, () => setState(() {})); + } + + void toggleTimeSpan(BuildContext context, TimeSpan timeSpan) { + pangeaController.analytics.setCurrentAnalyticsTimeSpan(timeSpan); + setState(() {}); + widget.refreshData(context).then((value) => setState(() {})); + } + + void toggleSelectedView(BarChartViewSelection view) { + selectedView = view; + if (!enableSelection(selected)) { + toggleSelection(selected!); + } + setState(() {}); + } + + bool enableSelection(AnalyticsSelected? selectedParam) { + return selectedView == BarChartViewSelection.grammar && + selectedParam?.type == AnalyticsEntryType.room + ? Matrix.of(context) + .client + .getRoomById(selectedParam!.id) + ?.membership == + Membership.join + : true; + } + + @override + Widget build(BuildContext context) { + return BaseAnalyticsView(controller: this); + } +} + +class TabData { + AnalyticsEntryType type; + IconData icon; + List items; + bool allowNavigateOnSelect; + + TabData({ + required this.type, + required this.items, + required this.icon, + this.allowNavigateOnSelect = true, + }); +} + +class TabItem { + Uri? avatar; + String displayName; + String id; + + TabItem({required this.avatar, required this.displayName, required this.id}); +} + +enum AnalyticsEntryType { student, room, space, privateChats } + +class AnalyticsSelected { + String id; + AnalyticsEntryType type; + String displayName; + + AnalyticsSelected(this.id, this.type, this.displayName); +} diff --git a/lib/pangea/pages/analytics/base_analytics_view.dart b/lib/pangea/pages/analytics/base_analytics_view.dart new file mode 100644 index 000000000..7b98df66e --- /dev/null +++ b/lib/pangea/pages/analytics/base_analytics_view.dart @@ -0,0 +1,227 @@ +import 'dart:math'; + +import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/pangea/enum/bar_chart_view_enum.dart'; +import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; +import 'package:fluffychat/pangea/enum/time_span.dart'; +import 'package:fluffychat/pangea/pages/analytics/analytics_list_tile.dart'; +import 'package:fluffychat/pangea/pages/analytics/base_analytics.dart'; +import 'package:fluffychat/pangea/pages/analytics/construct_list.dart'; +import 'package:fluffychat/pangea/pages/analytics/messages_bar_chart.dart'; +import 'package:fluffychat/pangea/pages/analytics/time_span_menu_button.dart'; +import 'package:fluffychat/widgets/layouts/max_width_body.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; + +class BaseAnalyticsView extends StatelessWidget { + const BaseAnalyticsView({ + super.key, + required this.controller, + }); + + final BaseAnalyticsController controller; + + Widget chartView(BuildContext context) { + switch (controller.selectedView) { + case BarChartViewSelection.messages: + return MessagesBarChart( + chartAnalytics: controller.chartData( + context, + controller.selected, + ), + barChartTitle: controller.barTitle, + ); + case BarChartViewSelection.grammar: + return ConstructList( + constructType: ConstructType.grammar, + title: controller.barTitle, + defaultSelected: controller.widget.defaultSelected, + selected: controller.selected, + controller: controller, + pangeaController: controller.pangeaController, + ); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: true, + title: Text( + controller.widget.pageTitle, + style: TextStyle( + color: Theme.of(context).textTheme.bodyLarge!.color, + fontSize: 18, + fontWeight: FontWeight.w700, + ), + overflow: TextOverflow.clip, + textAlign: TextAlign.center, + ), + leading: IconButton( + icon: const Icon(Icons.arrow_back), + onPressed: controller.navigate, + ), + actions: [ + for (final view in BarChartViewSelection.values) + Container( + decoration: BoxDecoration( + shape: BoxShape.circle, + color: controller.selectedView == view + ? AppConfig.primaryColor + : null, + ), + child: IconButton( + isSelected: controller.selectedView == view, + icon: Icon(view.icon), + tooltip: view.string(context), + onPressed: () => controller.toggleSelectedView(view), + ), + ), + TimeSpanMenuButton( + value: controller.currentTimeSpan, + onChange: (TimeSpan value) => + controller.toggleTimeSpan(context, value), + ), + ], + ), + body: MaxWidthBody( + withScrolling: false, + child: Column( + children: [ + Expanded( + flex: 1, + child: chartView(context), + ), + Expanded( + flex: 1, + child: DefaultTabController( + length: 2, + child: Column( + children: [ + TabBar( + tabs: [ + ...controller.widget.tabs.map( + (tab) => Tab( + icon: Icon( + tab.icon, + color: Theme.of(context) + .colorScheme + .onSurfaceVariant, + ), + ), + ), + ], + ), + Expanded( + child: SingleChildScrollView( + child: SizedBox( + height: max( + controller.widget.tabs[0].items.length + 1, + controller.widget.tabs[1].items.length, + ) * + 72, + child: TabBarView( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + ...controller.widget.tabs[0].items.map( + (item) => AnalyticsListTile( + avatar: item.avatar, + model: controller.chartData( + context, + AnalyticsSelected( + item.id, + controller.widget.tabs[0].type, + "", + ), + ), + displayName: item.displayName, + id: item.id, + type: controller.widget.tabs[0].type, + selected: controller.isSelected(item.id), + enabled: controller.enableSelection( + AnalyticsSelected( + item.id, + controller.widget.tabs[0].type, + "", + ), + ), + showSpaceAnalytics: false, + onTap: (_) => controller.toggleSelection( + AnalyticsSelected( + item.id, + controller.widget.tabs[0].type, + item.displayName, + ), + ), + allowNavigateOnSelect: controller + .widget.tabs[0].allowNavigateOnSelect, + ), + ), + if (controller.widget.defaultSelected.type == + AnalyticsEntryType.space) + AnalyticsListTile( + avatar: null, + model: controller.chartData( + context, + AnalyticsSelected( + controller.widget.defaultSelected.id, + AnalyticsEntryType.privateChats, + L10n.of(context)!.allPrivateChats, + ), + ), + displayName: + L10n.of(context)!.allPrivateChats, + id: controller.widget.defaultSelected.id, + type: AnalyticsEntryType.privateChats, + allowNavigateOnSelect: false, + selected: controller.isSelected( + controller.widget.defaultSelected.id, + ), + onTap: controller.toggleSelection, + ), + ], + ), + Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: controller.widget.tabs[1].items + .map( + (item) => AnalyticsListTile( + avatar: item.avatar, + model: controller.chartData( + context, + AnalyticsSelected( + item.id, + controller.widget.tabs[1].type, + "", + ), + ), + displayName: item.displayName, + id: item.id, + type: controller.widget.tabs[1].type, + selected: + controller.isSelected(item.id), + onTap: controller.toggleSelection, + allowNavigateOnSelect: controller.widget + .tabs[1].allowNavigateOnSelect, + ), + ) + .toList(), + ), + ], + ), + ), + ), + ), + ], + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/utils/client_manager.dart b/lib/utils/client_manager.dart index 52f6a968c..0d9cbee90 100644 --- a/lib/utils/client_manager.dart +++ b/lib/utils/client_manager.dart @@ -6,7 +6,6 @@ import 'package:fluffychat/pangea/constants/pangea_event_types.dart'; import 'package:fluffychat/utils/custom_http_client.dart'; import 'package:fluffychat/utils/custom_image_resizer.dart'; import 'package:fluffychat/utils/init_with_restore.dart'; -import 'package:fluffychat/utils/matrix_sdk_extensions/flutter_hive_collections_database.dart'; import 'package:fluffychat/utils/platform_infos.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; @@ -122,7 +121,9 @@ abstract class ClientManager { }, logLevel: kReleaseMode ? Level.warning : Level.verbose, databaseBuilder: flutterMatrixSdkDatabaseBuilder, - legacyDatabaseBuilder: FlutterHiveCollectionsDatabase.databaseBuilder, + // #Pangea + // legacyDatabaseBuilder: FlutterHiveCollectionsDatabase.databaseBuilder, + // Pangea# supportedLoginTypes: { AuthenticationTypes.password, AuthenticationTypes.sso, diff --git a/lib/utils/matrix_sdk_extensions/flutter_matrix_sdk_database_builder.dart b/lib/utils/matrix_sdk_extensions/flutter_matrix_sdk_database_builder.dart index 3cc80e82e..447a3e45a 100644 --- a/lib/utils/matrix_sdk_extensions/flutter_matrix_sdk_database_builder.dart +++ b/lib/utils/matrix_sdk_extensions/flutter_matrix_sdk_database_builder.dart @@ -1,10 +1,10 @@ import 'dart:convert'; import 'dart:math'; +import 'package:fluffychat/utils/matrix_sdk_extensions/flutter_hive_collections_database.dart'; +import 'package:fluffychat/utils/platform_infos.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; - -import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:matrix/matrix.dart'; import 'package:path_provider/path_provider.dart'; @@ -12,36 +12,34 @@ import 'package:sqflite_common_ffi/sqflite_ffi.dart' as ffi; import 'package:sqflite_sqlcipher/sqflite.dart'; import 'package:universal_html/html.dart' as html; -import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/utils/client_manager.dart'; -import 'package:fluffychat/utils/matrix_sdk_extensions/flutter_hive_collections_database.dart'; -import 'package:fluffychat/utils/platform_infos.dart'; - Future flutterMatrixSdkDatabaseBuilder(Client client) async { MatrixSdkDatabase? database; try { database = await _constructDatabase(client); + // throw "error"; await database.open(); return database; } catch (e) { + // #Pangea // Try to delete database so that it can created again on next init: - database?.delete().catchError( - (e, s) => Logs().w( - 'Unable to delete database, after failed construction', - e, - s, - ), - ); + // database?.delete().catchError( + // (e, s) => Logs().w( + // 'Unable to delete database, after failed construction', + // e, + // s, + // ), + // ); // Send error notification: - final l10n = lookupL10n(PlatformDispatcher.instance.locale); - ClientManager.sendInitNotification( - l10n.initAppError, - l10n.databaseBuildErrorBody( - AppConfig.newIssueUrl.toString(), - e.toString(), - ), - ); + // final l10n = lookupL10n(PlatformDispatcher.instance.locale); + // ClientManager.sendInitNotification( + // l10n.initAppError, + // l10n.databaseBuildErrorBody( + // AppConfig.newIssueUrl.toString(), + // e.toString(), + // ), + // ); + // Pangea# return FlutterHiveCollectionsDatabase.databaseBuilder(client); }