parent
141d3c5175
commit
7d46892a39
@ -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();
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
@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
|
||||
}
|
||||
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
|
||||
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();
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue