3927 analytics tweaks (#3953)
* analytics page updates * add back download buttons
This commit is contained in:
parent
141d3c5175
commit
7d46892a39
18 changed files with 385 additions and 369 deletions
|
|
@ -29,6 +29,7 @@ import 'package:fluffychat/pages/settings_password/settings_password.dart';
|
|||
import 'package:fluffychat/pages/settings_security/settings_security.dart';
|
||||
import 'package:fluffychat/pages/settings_style/settings_style.dart';
|
||||
import 'package:fluffychat/pangea/activity_sessions/activity_session_start/activity_session_start_page.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/analytics_page/analytics_page.dart';
|
||||
import 'package:fluffychat/pangea/analytics_summary/progress_indicators_enum.dart';
|
||||
import 'package:fluffychat/pangea/chat_settings/pages/pangea_invitation_selection.dart';
|
||||
|
|
@ -344,29 +345,112 @@ abstract class AppRoutes {
|
|||
pageBuilder: (context, state) => defaultPageBuilder(
|
||||
context,
|
||||
state,
|
||||
AnalyticsPage(
|
||||
selectedIndicator: ProgressIndicatorEnum.fromString(
|
||||
state.uri.queryParameters['mode'] ?? 'vocab',
|
||||
),
|
||||
constructZoom: state.extra is ConstructIdentifier
|
||||
? state.extra as ConstructIdentifier
|
||||
: null,
|
||||
),
|
||||
const AnalyticsPage(),
|
||||
),
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: ':roomid',
|
||||
path: ConstructTypeEnum.morph.string,
|
||||
pageBuilder: (context, state) => defaultPageBuilder(
|
||||
context,
|
||||
state,
|
||||
ChatPage(
|
||||
roomId: state.pathParameters['roomid']!,
|
||||
eventId: state.uri.queryParameters['event'],
|
||||
backButton: BackButton(
|
||||
onPressed: () => context.go(
|
||||
"/rooms/analytics?mode=activities",
|
||||
AnalyticsPage(
|
||||
indicator: FluffyThemes.isColumnMode(context)
|
||||
? null
|
||||
: ProgressIndicatorEnum.morphsUsed,
|
||||
),
|
||||
),
|
||||
redirect: loggedOutRedirect,
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: ':construct',
|
||||
pageBuilder: (context, state) {
|
||||
final construct = ConstructIdentifier.fromString(
|
||||
state.pathParameters['construct']!,
|
||||
);
|
||||
return defaultPageBuilder(
|
||||
context,
|
||||
state,
|
||||
AnalyticsPage(
|
||||
indicator: ProgressIndicatorEnum.morphsUsed,
|
||||
construct: construct,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
GoRoute(
|
||||
path: ConstructTypeEnum.vocab.string,
|
||||
pageBuilder: (context, state) => defaultPageBuilder(
|
||||
context,
|
||||
state,
|
||||
AnalyticsPage(
|
||||
indicator: FluffyThemes.isColumnMode(context)
|
||||
? null
|
||||
: ProgressIndicatorEnum.wordsUsed,
|
||||
),
|
||||
),
|
||||
redirect: loggedOutRedirect,
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: ':construct',
|
||||
pageBuilder: (context, state) {
|
||||
final construct = ConstructIdentifier.fromString(
|
||||
state.pathParameters['construct']!,
|
||||
);
|
||||
return defaultPageBuilder(
|
||||
context,
|
||||
state,
|
||||
AnalyticsPage(
|
||||
indicator: ProgressIndicatorEnum.wordsUsed,
|
||||
construct: construct,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
GoRoute(
|
||||
path: 'activities',
|
||||
pageBuilder: (context, state) => defaultPageBuilder(
|
||||
context,
|
||||
state,
|
||||
AnalyticsPage(
|
||||
indicator: FluffyThemes.isColumnMode(context)
|
||||
? null
|
||||
: ProgressIndicatorEnum.activities,
|
||||
),
|
||||
),
|
||||
redirect: loggedOutRedirect,
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: ':roomid',
|
||||
pageBuilder: (context, state) => defaultPageBuilder(
|
||||
context,
|
||||
state,
|
||||
ChatPage(
|
||||
roomId: state.pathParameters['roomid']!,
|
||||
eventId: state.uri.queryParameters['event'],
|
||||
backButton: BackButton(
|
||||
onPressed: () => context.go(
|
||||
"/rooms/analytics/activities",
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
redirect: loggedOutRedirect,
|
||||
),
|
||||
],
|
||||
),
|
||||
GoRoute(
|
||||
path: 'level',
|
||||
pageBuilder: (context, state) => defaultPageBuilder(
|
||||
context,
|
||||
state,
|
||||
AnalyticsPage(
|
||||
indicator: FluffyThemes.isColumnMode(context)
|
||||
? null
|
||||
: ProgressIndicatorEnum.level,
|
||||
),
|
||||
),
|
||||
redirect: loggedOutRedirect,
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ import 'package:fluffychat/pangea/chat_settings/constants/pangea_room_types.dart
|
|||
import 'package:fluffychat/pangea/chat_settings/utils/delete_room.dart';
|
||||
import 'package:fluffychat/pangea/chat_settings/widgets/delete_space_dialog.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/firebase_analytics.dart';
|
||||
import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
|
||||
import 'package:fluffychat/pangea/subscription/widgets/subscription_snackbar.dart';
|
||||
import 'package:fluffychat/utils/localized_exception_extension.dart';
|
||||
|
|
@ -1164,8 +1163,6 @@ class ChatListController extends State<ChatList>
|
|||
|
||||
// #Pangea
|
||||
void _initPangeaControllers(Client client) {
|
||||
GoogleAnalytics.analyticsUserUpdate(client.userID);
|
||||
MatrixState.pangeaController.initControllers();
|
||||
if (mounted) {
|
||||
MatrixState.pangeaController.classController.joinCachedSpaceCode(context);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import 'package:fluffychat/pangea/analytics_details_popup/morph_analytics_list_v
|
|||
import 'package:fluffychat/pangea/analytics_details_popup/morph_details_view.dart';
|
||||
import 'package:fluffychat/pangea/analytics_details_popup/vocab_analytics_details_view.dart';
|
||||
import 'package:fluffychat/pangea/analytics_details_popup/vocab_analytics_list_view.dart';
|
||||
import 'package:fluffychat/pangea/analytics_downloads/analytics_download_button.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/constructs/construct_identifier.dart';
|
||||
|
|
@ -14,57 +13,38 @@ import 'package:fluffychat/pangea/morphs/morph_models.dart';
|
|||
import 'package:fluffychat/pangea/morphs/morph_repo.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
||||
class AnalyticsPopupWrapper extends StatefulWidget {
|
||||
const AnalyticsPopupWrapper({
|
||||
class ConstructAnalyticsView extends StatefulWidget {
|
||||
const ConstructAnalyticsView({
|
||||
super.key,
|
||||
this.constructZoom,
|
||||
required this.view,
|
||||
this.backButtonOverride,
|
||||
this.construct,
|
||||
});
|
||||
|
||||
final ConstructTypeEnum view;
|
||||
final ConstructIdentifier? constructZoom;
|
||||
final Widget? backButtonOverride;
|
||||
final ConstructIdentifier? construct;
|
||||
|
||||
@override
|
||||
AnalyticsPopupWrapperState createState() => AnalyticsPopupWrapperState();
|
||||
ConstructAnalyticsViewState createState() => ConstructAnalyticsViewState();
|
||||
}
|
||||
|
||||
class AnalyticsPopupWrapperState extends State<AnalyticsPopupWrapper> {
|
||||
ConstructIdentifier? localConstructZoom;
|
||||
ConstructTypeEnum localView = ConstructTypeEnum.vocab;
|
||||
class ConstructAnalyticsViewState extends State<ConstructAnalyticsView> {
|
||||
final TextEditingController searchController = TextEditingController();
|
||||
|
||||
MorphFeaturesAndTags morphs = defaultMorphMapping;
|
||||
List<MorphFeature> features = defaultMorphMapping.displayFeatures;
|
||||
|
||||
bool isSearching = false;
|
||||
final TextEditingController searchController = TextEditingController();
|
||||
ConstructLevelEnum? selectedConstructLevel;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
localView = widget.view;
|
||||
setConstructZoom(widget.constructZoom);
|
||||
_setMorphs();
|
||||
searchController.addListener(() {
|
||||
if (mounted) setState(() {});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant AnalyticsPopupWrapper oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (widget.constructZoom != oldWidget.constructZoom) {
|
||||
setConstructZoom(widget.constructZoom);
|
||||
}
|
||||
if (widget.view != oldWidget.view) {
|
||||
localView = widget.view;
|
||||
localConstructZoom = null;
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
searchController.dispose();
|
||||
|
|
@ -92,14 +72,6 @@ class AnalyticsPopupWrapperState extends State<AnalyticsPopupWrapper> {
|
|||
}
|
||||
}
|
||||
|
||||
void setConstructZoom(ConstructIdentifier? id) {
|
||||
if (id != null && id.type != localView) {
|
||||
localView = id.type;
|
||||
}
|
||||
localConstructZoom = id;
|
||||
setState(() => {});
|
||||
}
|
||||
|
||||
void setSelectedConstructLevel(ConstructLevelEnum level) {
|
||||
setState(() {
|
||||
selectedConstructLevel = selectedConstructLevel == level ? null : level;
|
||||
|
|
@ -116,34 +88,12 @@ class AnalyticsPopupWrapperState extends State<AnalyticsPopupWrapper> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
localConstructZoom != null
|
||||
? IconButton(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () {
|
||||
setConstructZoom(null);
|
||||
},
|
||||
)
|
||||
: const SizedBox(),
|
||||
const DownloadAnalyticsButton(),
|
||||
],
|
||||
),
|
||||
Expanded(
|
||||
child: localView == ConstructTypeEnum.morph
|
||||
? localConstructZoom == null
|
||||
? MorphAnalyticsListView(controller: this)
|
||||
: MorphDetailsView(constructId: localConstructZoom!)
|
||||
: localConstructZoom == null
|
||||
? VocabAnalyticsListView(controller: this)
|
||||
: VocabDetailsView(constructId: localConstructZoom!),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
return widget.view == ConstructTypeEnum.morph
|
||||
? widget.construct == null
|
||||
? MorphAnalyticsListView(controller: this)
|
||||
: MorphDetailsView(constructId: widget.construct!)
|
||||
: widget.construct == null
|
||||
? VocabAnalyticsListView(controller: this)
|
||||
: VocabDetailsView(constructId: widget.construct!);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/pangea/analytics_details_popup/analytics_details_popup.dart';
|
||||
import 'package:fluffychat/pangea/analytics_downloads/analytics_download_button.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_use_model.dart';
|
||||
import 'package:fluffychat/pangea/common/config/environment.dart';
|
||||
|
|
@ -18,7 +21,7 @@ import 'package:fluffychat/pangea/morphs/morph_icon.dart';
|
|||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
||||
class MorphAnalyticsListView extends StatelessWidget {
|
||||
final AnalyticsPopupWrapperState controller;
|
||||
final ConstructAnalyticsViewState controller;
|
||||
|
||||
const MorphAnalyticsListView({
|
||||
required this.controller,
|
||||
|
|
@ -40,6 +43,13 @@ class MorphAnalyticsListView extends StatelessWidget {
|
|||
),
|
||||
if (!InstructionsEnum.morphAnalyticsList.isToggledOff)
|
||||
const SizedBox(height: 16.0),
|
||||
if (kIsWeb)
|
||||
const Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
DownloadAnalyticsButton(),
|
||||
],
|
||||
),
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
key: const PageStorageKey<String>('morph-analytics'),
|
||||
|
|
@ -55,7 +65,6 @@ class MorphAnalyticsListView extends StatelessWidget {
|
|||
.getDisplayTags(feature.feature)
|
||||
.map((tag) => tag.toLowerCase())
|
||||
.toSet(),
|
||||
onConstructZoom: controller.setConstructZoom,
|
||||
),
|
||||
)
|
||||
: const SizedBox.shrink();
|
||||
|
|
@ -71,13 +80,11 @@ class MorphAnalyticsListView extends StatelessWidget {
|
|||
class MorphFeatureBox extends StatelessWidget {
|
||||
final String morphFeature;
|
||||
final Set<String> allTags;
|
||||
final void Function(ConstructIdentifier) onConstructZoom;
|
||||
|
||||
const MorphFeatureBox({
|
||||
super.key,
|
||||
required this.morphFeature,
|
||||
required this.allTags,
|
||||
required this.onConstructZoom,
|
||||
});
|
||||
|
||||
MorphFeaturesEnum get feature =>
|
||||
|
|
@ -148,7 +155,9 @@ class MorphFeatureBox extends StatelessWidget {
|
|||
morphFeature: morphFeature,
|
||||
morphTag: morphTag,
|
||||
constructAnalytics: analytics,
|
||||
onTap: () => onConstructZoom(id),
|
||||
onTap: () => context.go(
|
||||
"/rooms/analytics/${id.type.string}/${id.string}",
|
||||
),
|
||||
);
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -36,87 +36,11 @@ class MorphDetailsView extends StatelessWidget {
|
|||
morphTag: _morphTag,
|
||||
textColor: textColor,
|
||||
),
|
||||
headerContent: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Expanded(
|
||||
child: MorphMeaningWidget(
|
||||
feature: _morphFeature,
|
||||
tag: _morphTag,
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
// leading: TextSpan(
|
||||
// text: L10n.of(context).meaningSectionHeader,
|
||||
// style: const TextStyle(
|
||||
// fontWeight: FontWeight.bold,
|
||||
// ),
|
||||
// ),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
headerContent: MorphMeaningWidget(
|
||||
feature: _morphFeature,
|
||||
tag: _morphTag,
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
// headerContent: Padding(
|
||||
// padding: const EdgeInsets.all(25.0),
|
||||
// child: Align(
|
||||
// alignment: Alignment.topLeft,
|
||||
// child: FutureBuilder(
|
||||
// future: _getDefinition(context),
|
||||
// builder: (
|
||||
// BuildContext context,
|
||||
// AsyncSnapshot<String?> snapshot,
|
||||
// ) {
|
||||
// if (snapshot.hasData) {
|
||||
// return MorphMeaningWidget(
|
||||
// feature: _morphFeature,
|
||||
// tag: _morphTag,
|
||||
// style: Theme.of(context).textTheme.bodyLarge,
|
||||
// leading: TextSpan(
|
||||
// text: L10n.of(context).meaningSectionHeader,
|
||||
// style: const TextStyle(
|
||||
// fontWeight: FontWeight.bold,
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// } else if (snapshot.hasError) {
|
||||
// return Wrap(
|
||||
// children: [
|
||||
// Text(
|
||||
// L10n.of(context).meaningSectionHeader,
|
||||
// style: Theme.of(context).textTheme.bodyLarge?.copyWith(
|
||||
// fontWeight: FontWeight.bold,
|
||||
// ),
|
||||
// ),
|
||||
// const SizedBox(
|
||||
// width: 10,
|
||||
// ),
|
||||
// Text(
|
||||
// L10n.of(context).meaningNotFound,
|
||||
// style: Theme.of(context).textTheme.bodyLarge,
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// } else {
|
||||
// return Wrap(
|
||||
// children: [
|
||||
// Text(
|
||||
// L10n.of(context).meaningSectionHeader,
|
||||
// style: Theme.of(context).textTheme.bodyLarge?.copyWith(
|
||||
// fontWeight: FontWeight.bold,
|
||||
// ),
|
||||
// ),
|
||||
// const SizedBox(
|
||||
// width: 10,
|
||||
// ),
|
||||
// const TextLoadingShimmer(width: 100),
|
||||
// ],
|
||||
// );
|
||||
// }
|
||||
// },
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
xpIcon: ConstructXpWidget(id: constructId),
|
||||
constructId: constructId,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/pangea/analytics_details_popup/analytics_details_popup.dart';
|
||||
import 'package:fluffychat/pangea/analytics_details_popup/vocab_analytics_list_tile.dart';
|
||||
import 'package:fluffychat/pangea/analytics_downloads/analytics_download_button.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_use_model.dart';
|
||||
import 'package:fluffychat/pangea/constructs/construct_level_enum.dart';
|
||||
|
|
@ -15,7 +18,7 @@ import 'package:fluffychat/widgets/matrix.dart';
|
|||
/// Displays vocab analytics, sorted into categories
|
||||
/// (flowers, greens, and seeds) by points
|
||||
class VocabAnalyticsListView extends StatelessWidget {
|
||||
final AnalyticsPopupWrapperState controller;
|
||||
final ConstructAnalyticsViewState controller;
|
||||
|
||||
const VocabAnalyticsListView({
|
||||
super.key,
|
||||
|
|
@ -79,6 +82,10 @@ class VocabAnalyticsListView extends StatelessWidget {
|
|||
),
|
||||
);
|
||||
|
||||
if (kIsWeb) {
|
||||
filters.add(const DownloadAnalyticsButton());
|
||||
}
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
const InstructionsInlineTooltip(
|
||||
|
|
@ -123,7 +130,7 @@ class VocabAnalyticsListView extends StatelessWidget {
|
|||
)
|
||||
: Row(
|
||||
spacing: FluffyThemes.isColumnMode(context) ? 16.0 : 4.0,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
key: const ValueKey('filters'),
|
||||
children: filters,
|
||||
),
|
||||
|
|
@ -143,7 +150,9 @@ class VocabAnalyticsListView extends StatelessWidget {
|
|||
itemBuilder: (context, index) {
|
||||
final vocabItem = _filteredVocab[index];
|
||||
return VocabAnalyticsListTile(
|
||||
onTap: () => controller.setConstructZoom(vocabItem.id),
|
||||
onTap: () => context.go(
|
||||
"/rooms/analytics/${vocabItem.id.type.string}/${vocabItem.id.string}",
|
||||
),
|
||||
constructUse: vocabItem,
|
||||
emoji: vocabItem.id.userSetEmoji.firstOrNull ??
|
||||
vocabItem.id.getLemmaInfoCached()?.emoji.firstOrNull,
|
||||
|
|
|
|||
|
|
@ -1,29 +1,108 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/analytics_page/activity_archive_view.dart';
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/pangea/activity_sessions/activity_room_extension.dart';
|
||||
import 'package:fluffychat/widgets/hover_builder.dart';
|
||||
import 'package:fluffychat/widgets/layouts/max_width_body.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import '../../config/themes.dart';
|
||||
import '../../widgets/avatar.dart';
|
||||
|
||||
class ActivityArchive extends StatefulWidget {
|
||||
class ActivityArchive extends StatelessWidget {
|
||||
const ActivityArchive({super.key});
|
||||
|
||||
@override
|
||||
ActivityArchiveState createState() => ActivityArchiveState();
|
||||
}
|
||||
|
||||
class ActivityArchiveState extends State<ActivityArchive> {
|
||||
List<Room> get archive =>
|
||||
MatrixState.pangeaController.getAnalytics.archivedActivities;
|
||||
|
||||
Future<void> removeArchivedChat(Room room) async {
|
||||
await room.leave();
|
||||
await MatrixState.pangeaController.putAnalytics
|
||||
.removeActivityAnalytics(room.id);
|
||||
|
||||
setState(() {});
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaxWidthBody(
|
||||
withScrolling: false,
|
||||
child: Builder(
|
||||
builder: (BuildContext context) {
|
||||
if (archive.isEmpty) {
|
||||
return const Center(
|
||||
child: Icon(Icons.archive_outlined, size: 80),
|
||||
);
|
||||
}
|
||||
return ListView.builder(
|
||||
itemCount: archive.length,
|
||||
itemBuilder: (BuildContext context, int i) => AnalyticsActivityItem(
|
||||
room: archive[i],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AnalyticsActivityItem extends StatelessWidget {
|
||||
final Room room;
|
||||
const AnalyticsActivityItem({
|
||||
super.key,
|
||||
required this.room,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => ActivityArchiveView(controller: this);
|
||||
Widget build(BuildContext context) {
|
||||
final objective = room.activityPlan?.learningObjective ?? '';
|
||||
final cefrLevel = room.activitySummary?.summary?.participants
|
||||
.firstWhereOrNull(
|
||||
(p) => p.participantId == room.client.userID,
|
||||
)
|
||||
?.cefrLevel;
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8,
|
||||
vertical: 1,
|
||||
),
|
||||
child: Material(
|
||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: ListTile(
|
||||
visualDensity: const VisualDensity(vertical: -0.5),
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
leading: HoverBuilder(
|
||||
builder: (context, hovered) => AnimatedScale(
|
||||
duration: FluffyThemes.animationDuration,
|
||||
curve: FluffyThemes.animationCurve,
|
||||
scale: hovered ? 1.1 : 1.0,
|
||||
child: Avatar(
|
||||
borderRadius: BorderRadius.circular(4.0),
|
||||
mxContent: room.avatar,
|
||||
name: room.getLocalizedDisplayname(),
|
||||
),
|
||||
),
|
||||
),
|
||||
title: Text(
|
||||
objective,
|
||||
maxLines: 3,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(fontSize: 12.0),
|
||||
),
|
||||
trailing: cefrLevel != null
|
||||
? Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8,
|
||||
vertical: 4,
|
||||
),
|
||||
child: Text(
|
||||
cefrLevel.toUpperCase(),
|
||||
style: const TextStyle(fontSize: 14.0),
|
||||
),
|
||||
)
|
||||
: null,
|
||||
onTap: () => context.go(
|
||||
'/rooms/analytics/activities/${room.id}',
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import 'package:fluffychat/pages/chat_list/chat_list_item.dart';
|
||||
import 'package:fluffychat/pangea/analytics_page/activity_archive.dart';
|
||||
import 'package:fluffychat/widgets/future_loading_dialog.dart';
|
||||
import 'package:fluffychat/widgets/layouts/max_width_body.dart';
|
||||
|
||||
class ActivityArchiveView extends StatelessWidget {
|
||||
final ActivityArchiveState controller;
|
||||
const ActivityArchiveView({
|
||||
super.key,
|
||||
required this.controller,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaxWidthBody(
|
||||
withScrolling: false,
|
||||
child: Builder(
|
||||
builder: (BuildContext context) {
|
||||
if (controller.archive.isEmpty) {
|
||||
return const Center(
|
||||
child: Icon(Icons.archive_outlined, size: 80),
|
||||
);
|
||||
}
|
||||
return ListView.builder(
|
||||
itemCount: controller.archive.length,
|
||||
itemBuilder: (BuildContext context, int i) => ChatListItem(
|
||||
controller.archive[i],
|
||||
onForget: () {
|
||||
showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () => controller.removeArchivedChat(
|
||||
controller.archive[i],
|
||||
),
|
||||
);
|
||||
},
|
||||
onTap: () =>
|
||||
context.go('/rooms/analytics/${controller.archive[i].id}'),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,46 +1,89 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/analytics_page/analytics_page_view.dart';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/pangea/analytics_details_popup/analytics_details_popup.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/analytics_page/activity_archive.dart';
|
||||
import 'package:fluffychat/pangea/analytics_page/analytics_page_constants.dart';
|
||||
import 'package:fluffychat/pangea/analytics_summary/learning_progress_indicators.dart';
|
||||
import 'package:fluffychat/pangea/analytics_summary/level_dialog_content.dart';
|
||||
import 'package:fluffychat/pangea/analytics_summary/progress_indicators_enum.dart';
|
||||
import 'package:fluffychat/pangea/constructs/construct_identifier.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
||||
class AnalyticsPage extends StatefulWidget {
|
||||
final ProgressIndicatorEnum? selectedIndicator;
|
||||
final ConstructIdentifier? constructZoom;
|
||||
class AnalyticsPage extends StatelessWidget {
|
||||
final ProgressIndicatorEnum? indicator;
|
||||
final ConstructIdentifier? construct;
|
||||
final bool isSidebar;
|
||||
|
||||
const AnalyticsPage({
|
||||
super.key,
|
||||
this.selectedIndicator,
|
||||
this.constructZoom,
|
||||
this.indicator,
|
||||
this.construct,
|
||||
this.isSidebar = false,
|
||||
});
|
||||
|
||||
@override
|
||||
AnalyticsPageState createState() => AnalyticsPageState();
|
||||
}
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: construct != null ? AppBar() : null,
|
||||
body: SafeArea(
|
||||
child: Padding(
|
||||
padding: const EdgeInsetsGeometry.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (isSidebar ||
|
||||
(!FluffyThemes.isColumnMode(context) && construct == null))
|
||||
LearningProgressIndicators(
|
||||
selected: indicator,
|
||||
canSelect: indicator != ProgressIndicatorEnum.level,
|
||||
),
|
||||
Expanded(
|
||||
child: StreamBuilder(
|
||||
stream: MatrixState
|
||||
.pangeaController.getAnalytics.analyticsStream.stream,
|
||||
builder: (context, _) {
|
||||
if (indicator == ProgressIndicatorEnum.level) {
|
||||
return const LevelDialogContent();
|
||||
} else if (indicator == ProgressIndicatorEnum.morphsUsed) {
|
||||
return ConstructAnalyticsView(
|
||||
construct: construct,
|
||||
view: ConstructTypeEnum.morph,
|
||||
);
|
||||
} else if (indicator == ProgressIndicatorEnum.wordsUsed) {
|
||||
return ConstructAnalyticsView(
|
||||
construct: construct,
|
||||
view: ConstructTypeEnum.vocab,
|
||||
);
|
||||
} else if (indicator == ProgressIndicatorEnum.activities) {
|
||||
return const ActivityArchive();
|
||||
}
|
||||
|
||||
class AnalyticsPageState extends State<AnalyticsPage> {
|
||||
ProgressIndicatorEnum? selectedIndicator = ProgressIndicatorEnum.wordsUsed;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// init the analytics controllers
|
||||
MatrixState.pangeaController.initControllers();
|
||||
selectedIndicator = widget.selectedIndicator ??
|
||||
ProgressIndicatorEnum.wordsUsed; // Default to wordsUsed if not set
|
||||
return Center(
|
||||
child: SizedBox(
|
||||
width: 250.0,
|
||||
child: CachedNetworkImage(
|
||||
imageUrl:
|
||||
"${AppConfig.assetsBaseURL}/${AnalyticsPageConstants.dinoBotFileName}",
|
||||
errorWidget: (context, url, error) =>
|
||||
const SizedBox(),
|
||||
placeholder: (context, url) => const Center(
|
||||
child: CircularProgressIndicator.adaptive(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant AnalyticsPage oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (oldWidget.selectedIndicator != widget.selectedIndicator &&
|
||||
widget.selectedIndicator != null) {
|
||||
setState(
|
||||
() => selectedIndicator = widget.selectedIndicator!,
|
||||
); // Update to new value
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => AnalyticsPageView(controller: this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,68 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/analytics_details_popup/analytics_details_popup.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/analytics_page/activity_archive.dart';
|
||||
import 'package:fluffychat/pangea/analytics_page/analytics_page.dart';
|
||||
import 'package:fluffychat/pangea/analytics_summary/learning_progress_indicators.dart';
|
||||
import 'package:fluffychat/pangea/analytics_summary/level_dialog_content.dart';
|
||||
import 'package:fluffychat/pangea/analytics_summary/progress_indicators_enum.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
||||
class AnalyticsPageView extends StatelessWidget {
|
||||
final AnalyticsPageState controller;
|
||||
const AnalyticsPageView({
|
||||
super.key,
|
||||
required this.controller,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: SafeArea(
|
||||
child: Padding(
|
||||
padding: const EdgeInsetsGeometry.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
LearningProgressIndicators(
|
||||
selected: controller.selectedIndicator,
|
||||
canSelect:
|
||||
controller.selectedIndicator != ProgressIndicatorEnum.level,
|
||||
),
|
||||
Expanded(
|
||||
child: StreamBuilder(
|
||||
stream: MatrixState
|
||||
.pangeaController.getAnalytics.analyticsStream.stream,
|
||||
builder: (context, _) {
|
||||
if (controller.selectedIndicator ==
|
||||
ProgressIndicatorEnum.level) {
|
||||
return const LevelDialogContent();
|
||||
} else if (controller.selectedIndicator ==
|
||||
ProgressIndicatorEnum.morphsUsed) {
|
||||
return AnalyticsPopupWrapper(
|
||||
constructZoom: controller.widget.constructZoom,
|
||||
view: ConstructTypeEnum.morph,
|
||||
);
|
||||
} else if (controller.selectedIndicator ==
|
||||
ProgressIndicatorEnum.wordsUsed) {
|
||||
return AnalyticsPopupWrapper(
|
||||
constructZoom: controller.widget.constructZoom,
|
||||
view: ConstructTypeEnum.vocab,
|
||||
);
|
||||
} else if (controller.selectedIndicator ==
|
||||
ProgressIndicatorEnum.activities) {
|
||||
return const ActivityArchive();
|
||||
}
|
||||
|
||||
return const SizedBox();
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -123,7 +123,7 @@ class LearningProgressIndicatorsState
|
|||
selected: widget.selected == c.indicator,
|
||||
onPressed: () {
|
||||
context.go(
|
||||
"/rooms/analytics?mode=${c.string}",
|
||||
"/rooms/analytics/${c.string}",
|
||||
);
|
||||
},
|
||||
child: ProgressIndicatorBadge(
|
||||
|
|
@ -138,7 +138,7 @@ class LearningProgressIndicatorsState
|
|||
ProgressIndicatorEnum.activities,
|
||||
onPressed: () {
|
||||
context.go(
|
||||
"/rooms/analytics?mode=activities",
|
||||
"/rooms/analytics/activities",
|
||||
);
|
||||
},
|
||||
child: Tooltip(
|
||||
|
|
@ -232,7 +232,7 @@ class LearningProgressIndicatorsState
|
|||
child: GestureDetector(
|
||||
onTap: widget.canSelect
|
||||
? () {
|
||||
context.go("/rooms/analytics?mode=level");
|
||||
context.go("/rooms/analytics/level");
|
||||
}
|
||||
: null,
|
||||
child: Row(
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import 'package:go_router/go_router.dart';
|
|||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/overlay.dart';
|
||||
import 'package:fluffychat/pangea/constructs/construct_identifier.dart';
|
||||
import 'package:fluffychat/pangea/morphs/get_grammar_copy.dart';
|
||||
|
|
@ -167,8 +168,7 @@ class ConstructNotificationOverlayState
|
|||
|
||||
void _showDetails() {
|
||||
context.go(
|
||||
"/rooms/analytics?mode=morph",
|
||||
extra: widget.construct,
|
||||
"/rooms/analytics/${ConstructTypeEnum.morph.string}/${widget.construct.string}",
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -102,11 +102,11 @@ class MessageAnalyticsFeedbackState extends State<MessageAnalyticsFeedback>
|
|||
void _showAnalyticsDialog(ConstructTypeEnum? type) {
|
||||
switch (type) {
|
||||
case ConstructTypeEnum.morph:
|
||||
context.go("/rooms/analytics?mode=morph");
|
||||
context.go("/rooms/analytics/${ConstructTypeEnum.morph.string}");
|
||||
break;
|
||||
case ConstructTypeEnum.vocab:
|
||||
default:
|
||||
context.go("/rooms/analytics?mode=vocab");
|
||||
context.go("/rooms/analytics/${ConstructTypeEnum.vocab.string}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ class PangeaController {
|
|||
PangeaController({required this.matrix, required this.matrixState}) {
|
||||
_setup();
|
||||
_setLanguageSubscription();
|
||||
_initControllers();
|
||||
randomint = Random().nextInt(2000);
|
||||
}
|
||||
|
||||
|
|
@ -74,12 +75,10 @@ class PangeaController {
|
|||
/// 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();
|
||||
void _initControllers() {
|
||||
_initAnalyticsControllers();
|
||||
subscriptionController.initialize();
|
||||
setPangeaPushRules();
|
||||
|
||||
TtsController.setAvailableLanguages();
|
||||
}
|
||||
|
||||
|
|
@ -181,8 +180,7 @@ class PangeaController {
|
|||
case LoginState.loggedOut:
|
||||
case LoginState.softLoggedOut:
|
||||
// Reset cached analytics data
|
||||
putAnalytics.dispose();
|
||||
getAnalytics.dispose();
|
||||
_disposeAnalyticsControllers();
|
||||
userController.clear();
|
||||
_languageStream?.cancel();
|
||||
_languageStream = null;
|
||||
|
|
@ -190,8 +188,7 @@ class PangeaController {
|
|||
break;
|
||||
case LoginState.loggedIn:
|
||||
// Initialize analytics data
|
||||
putAnalytics.initialize();
|
||||
getAnalytics.initialize();
|
||||
_initControllers();
|
||||
_setLanguageSubscription();
|
||||
|
||||
userController.reinitialize().then((_) {
|
||||
|
|
@ -213,13 +210,21 @@ class PangeaController {
|
|||
GoogleAnalytics.analyticsUserUpdate(userID);
|
||||
}
|
||||
|
||||
Future<void> resetAnalytics() async {
|
||||
putAnalytics.dispose();
|
||||
getAnalytics.dispose();
|
||||
Future<void> _initAnalyticsControllers() async {
|
||||
putAnalytics.initialize();
|
||||
await getAnalytics.initialize();
|
||||
}
|
||||
|
||||
void _disposeAnalyticsControllers() {
|
||||
putAnalytics.dispose();
|
||||
getAnalytics.dispose();
|
||||
}
|
||||
|
||||
Future<void> resetAnalytics() async {
|
||||
_disposeAnalyticsControllers();
|
||||
await _initAnalyticsControllers();
|
||||
}
|
||||
|
||||
void _setLanguageSubscription() {
|
||||
_languageStream?.cancel();
|
||||
_languageStream = userController.languageStream.stream.listen(
|
||||
|
|
@ -228,6 +233,7 @@ class PangeaController {
|
|||
}
|
||||
|
||||
Future<void> setPangeaPushRules() async {
|
||||
if (!matrixState.client.isLogged()) return;
|
||||
final List<Room> analyticsRooms =
|
||||
matrixState.client.rooms.where((room) => room.isAnalyticsRoom).toList();
|
||||
|
||||
|
|
|
|||
|
|
@ -119,6 +119,28 @@ class ConstructIdentifier {
|
|||
return "$lemma:${type.string}-$category".toLowerCase();
|
||||
}
|
||||
|
||||
static ConstructIdentifier? fromString(String s) {
|
||||
final parts = s.split(':');
|
||||
if (parts.length != 2) return null;
|
||||
final lemma = parts[0];
|
||||
final typeAndCategory = parts[1].split('-');
|
||||
if (typeAndCategory.length != 2) return null;
|
||||
final typeString = typeAndCategory[0];
|
||||
final category = typeAndCategory[1];
|
||||
|
||||
final type = ConstructTypeEnum.values.firstWhereOrNull(
|
||||
(e) => e.string == typeString,
|
||||
);
|
||||
|
||||
if (type == null) return null;
|
||||
|
||||
return ConstructIdentifier(
|
||||
lemma: lemma,
|
||||
type: type,
|
||||
category: category,
|
||||
);
|
||||
}
|
||||
|
||||
String get partialKey => "$lemma-${type.string}";
|
||||
|
||||
ConstructUses get constructUses =>
|
||||
|
|
|
|||
|
|
@ -279,8 +279,7 @@ class MorphMeaningPopupState extends State<MorphMeaningPopup> {
|
|||
ConstructXpWidget(
|
||||
id: widget.cId,
|
||||
onTap: () => context.go(
|
||||
"/rooms/analytics?mode=morph",
|
||||
extra: widget.cId,
|
||||
"/rooms/analytics/${ConstructTypeEnum.morph.string}/${widget.cId.string}",
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import 'package:go_router/go_router.dart';
|
|||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/common/widgets/error_indicator.dart';
|
||||
import 'package:fluffychat/pangea/events/event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/events/models/pangea_token_model.dart';
|
||||
|
|
@ -107,8 +108,7 @@ class WordZoomWidget extends StatelessWidget {
|
|||
ConstructXpWidget(
|
||||
id: token.vocabConstructID,
|
||||
onTap: () => context.go(
|
||||
"/rooms/analytics?mode=vocab",
|
||||
extra: token.vocabConstructID,
|
||||
"/rooms/analytics/${ConstructTypeEnum.vocab.string}/${token.vocabConstructID.string}",
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@ import 'package:fluffychat/config/app_config.dart';
|
|||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/pages/chat_list/chat_list.dart';
|
||||
import 'package:fluffychat/pages/settings/settings.dart';
|
||||
import 'package:fluffychat/pangea/analytics_page/analytics_page_constants.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/analytics_page/analytics_page.dart';
|
||||
import 'package:fluffychat/pangea/analytics_summary/progress_indicators_enum.dart';
|
||||
import 'package:fluffychat/pangea/find_your_people/find_your_people_constants.dart';
|
||||
import 'package:fluffychat/widgets/navigation_rail.dart';
|
||||
|
||||
|
|
@ -37,7 +39,7 @@ class TwoColumnLayout extends StatelessWidget {
|
|||
final spaceID = state.pathParameters['spaceid'];
|
||||
|
||||
if (roomID == null && spaceID == null) {
|
||||
showNavRail = !["newcourse"].any(
|
||||
showNavRail = !["newcourse", ":construct"].any(
|
||||
(p) => state.fullPath?.contains(p) ?? false,
|
||||
);
|
||||
} else if (roomID == null) {
|
||||
|
|
@ -100,17 +102,6 @@ class _MainView extends StatelessWidget {
|
|||
required this.state,
|
||||
});
|
||||
|
||||
String get _asset {
|
||||
const defaultAsset = FindYourPeopleConstants.sideBearFileName;
|
||||
if (state.fullPath == null || state.fullPath!.isEmpty) return defaultAsset;
|
||||
|
||||
if (state.fullPath!.contains('analytics')) {
|
||||
return AnalyticsPageConstants.dinoBotFileName;
|
||||
}
|
||||
|
||||
return defaultAsset;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final path = state.fullPath;
|
||||
|
|
@ -121,16 +112,35 @@ class _MainView extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
if (path.contains("analytics")) {
|
||||
ProgressIndicatorEnum indicator = ProgressIndicatorEnum.wordsUsed;
|
||||
if (path.contains("analytics/level")) {
|
||||
indicator = ProgressIndicatorEnum.level;
|
||||
} else if (path.contains("analytics/${ConstructTypeEnum.morph.string}")) {
|
||||
indicator = ProgressIndicatorEnum.morphsUsed;
|
||||
} else if (path.contains("analytics/${ConstructTypeEnum.vocab.string}")) {
|
||||
indicator = ProgressIndicatorEnum.wordsUsed;
|
||||
} else if (path.contains("analytics/activities")) {
|
||||
indicator = ProgressIndicatorEnum.activities;
|
||||
}
|
||||
|
||||
return AnalyticsPage(
|
||||
indicator: indicator,
|
||||
isSidebar: true,
|
||||
);
|
||||
}
|
||||
|
||||
if (path.contains("settings")) {
|
||||
return Settings(key: state.pageKey);
|
||||
}
|
||||
|
||||
if (['communities', 'analytics'].any((p) => path.contains(p))) {
|
||||
if (path.contains('communities')) {
|
||||
return Center(
|
||||
child: SizedBox(
|
||||
width: 250.0,
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: "${AppConfig.assetsBaseURL}/$_asset",
|
||||
imageUrl:
|
||||
"${AppConfig.assetsBaseURL}/${FindYourPeopleConstants.sideBearFileName}",
|
||||
errorWidget: (context, url, error) => const SizedBox(),
|
||||
placeholder: (context, url) => const Center(
|
||||
child: CircularProgressIndicator.adaptive(),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue