fix: remove public course route between find a course and public course preview

This commit is contained in:
ggurdin 2026-01-27 13:00:47 -05:00
parent 0c0cadb743
commit 2a4c962692
No known key found for this signature in database
GPG key ID: A01CB41737CBB478
4 changed files with 540 additions and 555 deletions

View file

@ -57,7 +57,6 @@ import 'package:fluffychat/pangea/login/pages/find_course_page.dart';
import 'package:fluffychat/pangea/login/pages/language_selection_page.dart';
import 'package:fluffychat/pangea/login/pages/login_or_signup_view.dart';
import 'package:fluffychat/pangea/login/pages/new_course_page.dart';
import 'package:fluffychat/pangea/login/pages/public_courses_page.dart';
import 'package:fluffychat/pangea/login/pages/signup.dart';
import 'package:fluffychat/pangea/space_analytics/space_analytics.dart';
import 'package:fluffychat/pangea/spaces/space_constants.dart';
@ -364,32 +363,18 @@ abstract class AppRoutes {
},
),
GoRoute(
path: 'public',
path: ':courseid',
pageBuilder: (context, state) {
return defaultPageBuilder(
context,
state,
const PublicCoursesPage(
route: 'rooms',
SelectedCourse(
state.pathParameters['courseid']!,
SelectedCourseMode.join,
roomChunk: state.extra as PublicRoomsChunk?,
),
);
},
routes: [
GoRoute(
path: ':courseid',
pageBuilder: (context, state) {
return defaultPageBuilder(
context,
state,
SelectedCourse(
state.pathParameters['courseid']!,
SelectedCourseMode.join,
roomChunk: state.extra as PublicRoomsChunk?,
),
);
},
),
],
),
GoRoute(
path: 'own',

View file

@ -1,163 +1,163 @@
import 'package:flutter/material.dart';
// import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:go_router/go_router.dart';
import 'package:material_symbols_icons/symbols.dart';
// import 'package:flutter_svg/svg.dart';
// import 'package:go_router/go_router.dart';
// import 'package:material_symbols_icons/symbols.dart';
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/l10n/l10n.dart';
import 'package:fluffychat/pangea/common/widgets/pangea_logo_svg.dart';
// import 'package:fluffychat/config/app_config.dart';
// import 'package:fluffychat/l10n/l10n.dart';
// import 'package:fluffychat/pangea/common/widgets/pangea_logo_svg.dart';
class AddCoursePage extends StatelessWidget {
final String route;
const AddCoursePage({
required this.route,
super.key,
});
// class AddCoursePage extends StatelessWidget {
// final String route;
// const AddCoursePage({
// required this.route,
// super.key,
// });
static String mapStartFileName = "start_trip.svg";
static String mapUnlockFileName = "unlock_trip.svg";
// static String mapStartFileName = "start_trip.svg";
// static String mapUnlockFileName = "unlock_trip.svg";
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Scaffold(
appBar: AppBar(
title: Row(
spacing: 10.0,
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.map_outlined),
Text(L10n.of(context).addCourse),
],
),
automaticallyImplyLeading: false,
centerTitle: true,
),
body: SafeArea(
child: Center(
child: Container(
padding: const EdgeInsets.all(20.0),
constraints: const BoxConstraints(
maxWidth: 350,
maxHeight: 600,
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
PangeaLogoSvg(
width: 100.0,
forceColor: theme.colorScheme.onSurface,
),
Column(
spacing: 16.0,
children: [
ElevatedButton(
onPressed: () => context.go(
'/$route/course/private',
),
style: ElevatedButton.styleFrom(
backgroundColor: theme.colorScheme.primaryContainer,
foregroundColor: theme.colorScheme.onPrimaryContainer,
),
child: Row(
spacing: 4.0,
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.network(
"${AppConfig.assetsBaseURL}/$mapUnlockFileName",
width: 24.0,
height: 24.0,
colorFilter: ColorFilter.mode(
theme.colorScheme.onPrimaryContainer,
BlendMode.srcIn,
),
),
Flexible(
child: Text(
L10n.of(context).joinWithCode,
textAlign: TextAlign.center,
),
),
],
),
),
ElevatedButton(
onPressed: () => context.go(
'/$route/course/public',
),
style: ElevatedButton.styleFrom(
backgroundColor: theme.colorScheme.primaryContainer,
foregroundColor: theme.colorScheme.onPrimaryContainer,
),
child: Row(
spacing: 4.0,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Symbols.map_search,
size: 24.0,
color: theme.colorScheme.onPrimaryContainer,
),
Flexible(
child: Text(
L10n.of(context).joinPublicCourse,
textAlign: TextAlign.center,
),
),
],
),
),
ElevatedButton(
onPressed: () => context.go(
'/$route/course/own',
),
style: ElevatedButton.styleFrom(
backgroundColor: theme.colorScheme.primaryContainer,
foregroundColor: theme.colorScheme.onPrimaryContainer,
),
child: Row(
spacing: 4.0,
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.network(
"${AppConfig.assetsBaseURL}/$mapStartFileName",
width: 24.0,
height: 24.0,
colorFilter: ColorFilter.mode(
theme.colorScheme.onPrimaryContainer,
BlendMode.srcIn,
),
),
Flexible(
child: Text(
L10n.of(context).startOwn,
textAlign: TextAlign.center,
),
),
],
),
),
ListTile(
contentPadding: const EdgeInsets.all(0.0),
leading: const Icon(Icons.school),
title: Text(
L10n.of(context).joinCourseDesc,
style: theme.textTheme.labelLarge,
),
),
if (route == "registration")
TextButton(
child: Text(L10n.of(context).skipForNow),
onPressed: () => context.go('/rooms'),
),
],
),
],
),
),
),
),
);
}
}
// @override
// Widget build(BuildContext context) {
// final theme = Theme.of(context);
// return Scaffold(
// appBar: AppBar(
// title: Row(
// spacing: 10.0,
// mainAxisSize: MainAxisSize.min,
// children: [
// const Icon(Icons.map_outlined),
// Text(L10n.of(context).addCourse),
// ],
// ),
// automaticallyImplyLeading: false,
// centerTitle: true,
// ),
// body: SafeArea(
// child: Center(
// child: Container(
// padding: const EdgeInsets.all(20.0),
// constraints: const BoxConstraints(
// maxWidth: 350,
// maxHeight: 600,
// ),
// child: Column(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// PangeaLogoSvg(
// width: 100.0,
// forceColor: theme.colorScheme.onSurface,
// ),
// Column(
// spacing: 16.0,
// children: [
// ElevatedButton(
// onPressed: () => context.go(
// '/$route/course/private',
// ),
// style: ElevatedButton.styleFrom(
// backgroundColor: theme.colorScheme.primaryContainer,
// foregroundColor: theme.colorScheme.onPrimaryContainer,
// ),
// child: Row(
// spacing: 4.0,
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// SvgPicture.network(
// "${AppConfig.assetsBaseURL}/$mapUnlockFileName",
// width: 24.0,
// height: 24.0,
// colorFilter: ColorFilter.mode(
// theme.colorScheme.onPrimaryContainer,
// BlendMode.srcIn,
// ),
// ),
// Flexible(
// child: Text(
// L10n.of(context).joinWithCode,
// textAlign: TextAlign.center,
// ),
// ),
// ],
// ),
// ),
// ElevatedButton(
// onPressed: () => context.go(
// '/$route/course/public',
// ),
// style: ElevatedButton.styleFrom(
// backgroundColor: theme.colorScheme.primaryContainer,
// foregroundColor: theme.colorScheme.onPrimaryContainer,
// ),
// child: Row(
// spacing: 4.0,
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// Icon(
// Symbols.map_search,
// size: 24.0,
// color: theme.colorScheme.onPrimaryContainer,
// ),
// Flexible(
// child: Text(
// L10n.of(context).joinPublicCourse,
// textAlign: TextAlign.center,
// ),
// ),
// ],
// ),
// ),
// ElevatedButton(
// onPressed: () => context.go(
// '/$route/course/own',
// ),
// style: ElevatedButton.styleFrom(
// backgroundColor: theme.colorScheme.primaryContainer,
// foregroundColor: theme.colorScheme.onPrimaryContainer,
// ),
// child: Row(
// spacing: 4.0,
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// SvgPicture.network(
// "${AppConfig.assetsBaseURL}/$mapStartFileName",
// width: 24.0,
// height: 24.0,
// colorFilter: ColorFilter.mode(
// theme.colorScheme.onPrimaryContainer,
// BlendMode.srcIn,
// ),
// ),
// Flexible(
// child: Text(
// L10n.of(context).startOwn,
// textAlign: TextAlign.center,
// ),
// ),
// ],
// ),
// ),
// ListTile(
// contentPadding: const EdgeInsets.all(0.0),
// leading: const Icon(Icons.school),
// title: Text(
// L10n.of(context).joinCourseDesc,
// style: theme.textTheme.labelLarge,
// ),
// ),
// if (route == "registration")
// TextButton(
// child: Text(L10n.of(context).skipForNow),
// onPressed: () => context.go('/rooms'),
// ),
// ],
// ),
// ],
// ),
// ),
// ),
// ),
// );
// }
// }

View file

@ -403,7 +403,7 @@ class _PublicCourseTile extends StatelessWidget {
type: MaterialType.transparency,
child: InkWell(
onTap: () => context.go(
'/rooms/course/public/$courseId',
'/rooms/course/$courseId',
extra: space,
),
borderRadius: BorderRadius.circular(12.0),
@ -482,7 +482,7 @@ class _PublicCourseTile extends StatelessWidget {
HoverBuilder(
builder: (context, hovered) => ElevatedButton(
onPressed: () => context.go(
'/rooms/course/public/$courseId',
'/rooms/course/$courseId',
extra: space,
),
style: ElevatedButton.styleFrom(

View file

@ -1,402 +1,402 @@
import 'package:flutter/material.dart';
// import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:matrix/matrix.dart';
// import 'package:go_router/go_router.dart';
// import 'package:matrix/matrix.dart';
import 'package:fluffychat/l10n/l10n.dart';
import 'package:fluffychat/pangea/bot/widgets/bot_face_svg.dart';
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
import 'package:fluffychat/pangea/common/widgets/url_image_widget.dart';
import 'package:fluffychat/pangea/course_creation/course_info_chip_widget.dart';
import 'package:fluffychat/pangea/course_creation/course_language_filter.dart';
import 'package:fluffychat/pangea/course_plans/courses/course_plan_model.dart';
import 'package:fluffychat/pangea/course_plans/courses/course_plans_repo.dart';
import 'package:fluffychat/pangea/course_plans/courses/get_localized_courses_request.dart';
import 'package:fluffychat/pangea/languages/language_model.dart';
import 'package:fluffychat/pangea/spaces/public_course_extension.dart';
import 'package:fluffychat/widgets/avatar.dart';
import 'package:fluffychat/widgets/hover_builder.dart';
import 'package:fluffychat/widgets/matrix.dart';
// import 'package:fluffychat/l10n/l10n.dart';
// import 'package:fluffychat/pangea/bot/widgets/bot_face_svg.dart';
// import 'package:fluffychat/pangea/common/utils/error_handler.dart';
// import 'package:fluffychat/pangea/common/widgets/url_image_widget.dart';
// import 'package:fluffychat/pangea/course_creation/course_info_chip_widget.dart';
// import 'package:fluffychat/pangea/course_creation/course_language_filter.dart';
// import 'package:fluffychat/pangea/course_plans/courses/course_plan_model.dart';
// import 'package:fluffychat/pangea/course_plans/courses/course_plans_repo.dart';
// import 'package:fluffychat/pangea/course_plans/courses/get_localized_courses_request.dart';
// import 'package:fluffychat/pangea/languages/language_model.dart';
// import 'package:fluffychat/pangea/spaces/public_course_extension.dart';
// import 'package:fluffychat/widgets/avatar.dart';
// import 'package:fluffychat/widgets/hover_builder.dart';
// import 'package:fluffychat/widgets/matrix.dart';
class PublicCoursesPage extends StatefulWidget {
final String route;
final bool showFilters;
const PublicCoursesPage({
super.key,
required this.route,
this.showFilters = true,
});
// class PublicCoursesPage extends StatefulWidget {
// final String route;
// final bool showFilters;
// const PublicCoursesPage({
// super.key,
// required this.route,
// this.showFilters = true,
// });
@override
State<PublicCoursesPage> createState() => PublicCoursesPageState();
}
// @override
// State<PublicCoursesPage> createState() => PublicCoursesPageState();
// }
class PublicCoursesPageState extends State<PublicCoursesPage> {
bool loading = true;
Object? error;
// class PublicCoursesPageState extends State<PublicCoursesPage> {
// bool loading = true;
// Object? error;
LanguageModel? targetLanguageFilter;
// LanguageModel? targetLanguageFilter;
List<PublicCoursesChunk> discoveredCourses = [];
Map<String, CoursePlanModel> coursePlans = {};
String? nextBatch;
// List<PublicCoursesChunk> discoveredCourses = [];
// Map<String, CoursePlanModel> coursePlans = {};
// String? nextBatch;
@override
void initState() {
super.initState();
// @override
// void initState() {
// super.initState();
final target = MatrixState.pangeaController.userController.userL2;
if (target != null) {
setTargetLanguageFilter(target);
}
// final target = MatrixState.pangeaController.userController.userL2;
// if (target != null) {
// setTargetLanguageFilter(target);
// }
_loadCourses();
}
// _loadCourses();
// }
void setTargetLanguageFilter(LanguageModel? language) {
if (targetLanguageFilter?.langCodeShort == language?.langCodeShort) return;
setState(() => targetLanguageFilter = language);
_loadCourses();
}
// void setTargetLanguageFilter(LanguageModel? language) {
// if (targetLanguageFilter?.langCodeShort == language?.langCodeShort) return;
// setState(() => targetLanguageFilter = language);
// _loadCourses();
// }
List<PublicCoursesChunk> get filteredCourses {
List<PublicCoursesChunk> filtered = discoveredCourses
.where(
(c) =>
!Matrix.of(context).client.rooms.any(
(r) =>
r.id == c.room.roomId &&
r.membership == Membership.join,
) &&
coursePlans.containsKey(c.courseId),
)
.toList();
// List<PublicCoursesChunk> get filteredCourses {
// List<PublicCoursesChunk> filtered = discoveredCourses
// .where(
// (c) =>
// !Matrix.of(context).client.rooms.any(
// (r) =>
// r.id == c.room.roomId &&
// r.membership == Membership.join,
// ) &&
// coursePlans.containsKey(c.courseId),
// )
// .toList();
if (targetLanguageFilter != null) {
filtered = filtered.where(
(chunk) {
final course = coursePlans[chunk.courseId];
if (course == null) return false;
return course.targetLanguage.split('-').first ==
targetLanguageFilter!.langCodeShort;
},
).toList();
}
// if (targetLanguageFilter != null) {
// filtered = filtered.where(
// (chunk) {
// final course = coursePlans[chunk.courseId];
// if (course == null) return false;
// return course.targetLanguage.split('-').first ==
// targetLanguageFilter!.langCodeShort;
// },
// ).toList();
// }
// sort by join rule, with knock rooms at the end
filtered.sort((a, b) {
final aKnock = a.room.joinRule == JoinRules.knock.name;
final bKnock = b.room.joinRule == JoinRules.knock.name;
if (aKnock && !bKnock) return 1;
if (!aKnock && bKnock) return -1;
return 0;
});
// // sort by join rule, with knock rooms at the end
// filtered.sort((a, b) {
// final aKnock = a.room.joinRule == JoinRules.knock.name;
// final bKnock = b.room.joinRule == JoinRules.knock.name;
// if (aKnock && !bKnock) return 1;
// if (!aKnock && bKnock) return -1;
// return 0;
// });
return filtered;
}
// return filtered;
// }
Future<void> _loadPublicSpaces() async {
try {
final resp = await Matrix.of(context).client.requestPublicCourses(
since: nextBatch,
);
// Future<void> _loadPublicSpaces() async {
// try {
// final resp = await Matrix.of(context).client.requestPublicCourses(
// since: nextBatch,
// );
for (final room in resp.courses) {
if (!discoveredCourses.any((e) => e.room.roomId == room.room.roomId)) {
discoveredCourses.add(room);
}
}
// for (final room in resp.courses) {
// if (!discoveredCourses.any((e) => e.room.roomId == room.room.roomId)) {
// discoveredCourses.add(room);
// }
// }
nextBatch = resp.nextBatch;
} catch (e, s) {
error = e;
ErrorHandler.logError(
e: e,
s: s,
data: {
'nextBatch': nextBatch,
},
);
}
}
// nextBatch = resp.nextBatch;
// } catch (e, s) {
// error = e;
// ErrorHandler.logError(
// e: e,
// s: s,
// data: {
// 'nextBatch': nextBatch,
// },
// );
// }
// }
Future<void> _loadCourses() async {
setState(() {
loading = true;
error = null;
});
// Future<void> _loadCourses() async {
// setState(() {
// loading = true;
// error = null;
// });
await _loadPublicSpaces();
// await _loadPublicSpaces();
int timesLoaded = 0;
while (error == null && timesLoaded < 5 && nextBatch != null) {
await _loadPublicSpaces();
timesLoaded++;
}
// int timesLoaded = 0;
// while (error == null && timesLoaded < 5 && nextBatch != null) {
// await _loadPublicSpaces();
// timesLoaded++;
// }
try {
final resp = await CoursePlansRepo.search(
GetLocalizedCoursesRequest(
coursePlanIds:
discoveredCourses.map((c) => c.courseId).toSet().toList(),
l1: MatrixState.pangeaController.userController.userL1Code!,
),
);
final searchResult = resp.coursePlans;
// try {
// final resp = await CoursePlansRepo.search(
// GetLocalizedCoursesRequest(
// coursePlanIds:
// discoveredCourses.map((c) => c.courseId).toSet().toList(),
// l1: MatrixState.pangeaController.userController.userL1Code!,
// ),
// );
// final searchResult = resp.coursePlans;
coursePlans.clear();
for (final entry in searchResult.entries) {
coursePlans[entry.key] = entry.value;
}
} catch (e, s) {
ErrorHandler.logError(
e: e,
s: s,
data: {
'discoveredCourses':
discoveredCourses.map((c) => c.courseId).toList(),
},
);
} finally {
if (mounted) {
setState(() => loading = false);
}
}
}
// coursePlans.clear();
// for (final entry in searchResult.entries) {
// coursePlans[entry.key] = entry.value;
// }
// } catch (e, s) {
// ErrorHandler.logError(
// e: e,
// s: s,
// data: {
// 'discoveredCourses':
// discoveredCourses.map((c) => c.courseId).toList(),
// },
// );
// } finally {
// if (mounted) {
// setState(() => loading = false);
// }
// }
// }
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Scaffold(
appBar: AppBar(
title: Text(
L10n.of(context).joinPublicCourse,
),
),
body: SafeArea(
child: Center(
child: Container(
padding: const EdgeInsets.all(20.0),
constraints: const BoxConstraints(
maxWidth: 450,
),
child: Column(
children: [
if (widget.showFilters) ...[
Row(
children: [
Expanded(
child: Wrap(
spacing: 8.0,
runSpacing: 8.0,
alignment: WrapAlignment.start,
children: [
CourseLanguageFilter(
value: targetLanguageFilter,
onChanged: setTargetLanguageFilter,
),
],
),
),
],
),
const SizedBox(height: 20.0),
],
if (error != null ||
(!loading && filteredCourses.isEmpty && nextBatch == null))
Center(
child: Padding(
padding: const EdgeInsets.all(32.0),
child: Column(
spacing: 12.0,
children: [
const BotFace(
expression: BotExpression.addled,
width: Avatar.defaultSize * 1.5,
),
Text(
L10n.of(context).noPublicCoursesFound,
textAlign: TextAlign.center,
style: theme.textTheme.bodyLarge,
),
ElevatedButton(
onPressed: () => context.go(
'/${widget.route}/course/own',
),
style: ElevatedButton.styleFrom(
backgroundColor:
theme.colorScheme.primaryContainer,
foregroundColor:
theme.colorScheme.onPrimaryContainer,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(L10n.of(context).startOwn),
],
),
),
],
),
),
)
else
Expanded(
child: ListView.separated(
itemCount: filteredCourses.length + 1,
separatorBuilder: (context, index) =>
const SizedBox(height: 10.0),
itemBuilder: (context, index) {
if (index == filteredCourses.length) {
return Center(
child: loading
? const CircularProgressIndicator.adaptive()
: nextBatch != null
? TextButton(
onPressed: _loadCourses,
child: Text(L10n.of(context).loadMore),
)
: const SizedBox(),
);
}
// @override
// Widget build(BuildContext context) {
// final theme = Theme.of(context);
// return Scaffold(
// appBar: AppBar(
// title: Text(
// L10n.of(context).joinPublicCourse,
// ),
// ),
// body: SafeArea(
// child: Center(
// child: Container(
// padding: const EdgeInsets.all(20.0),
// constraints: const BoxConstraints(
// maxWidth: 450,
// ),
// child: Column(
// children: [
// if (widget.showFilters) ...[
// Row(
// children: [
// Expanded(
// child: Wrap(
// spacing: 8.0,
// runSpacing: 8.0,
// alignment: WrapAlignment.start,
// children: [
// CourseLanguageFilter(
// value: targetLanguageFilter,
// onChanged: setTargetLanguageFilter,
// ),
// ],
// ),
// ),
// ],
// ),
// const SizedBox(height: 20.0),
// ],
// if (error != null ||
// (!loading && filteredCourses.isEmpty && nextBatch == null))
// Center(
// child: Padding(
// padding: const EdgeInsets.all(32.0),
// child: Column(
// spacing: 12.0,
// children: [
// const BotFace(
// expression: BotExpression.addled,
// width: Avatar.defaultSize * 1.5,
// ),
// Text(
// L10n.of(context).noPublicCoursesFound,
// textAlign: TextAlign.center,
// style: theme.textTheme.bodyLarge,
// ),
// ElevatedButton(
// onPressed: () => context.go(
// '/${widget.route}/course/own',
// ),
// style: ElevatedButton.styleFrom(
// backgroundColor:
// theme.colorScheme.primaryContainer,
// foregroundColor:
// theme.colorScheme.onPrimaryContainer,
// ),
// child: Row(
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// Text(L10n.of(context).startOwn),
// ],
// ),
// ),
// ],
// ),
// ),
// )
// else
// Expanded(
// child: ListView.separated(
// itemCount: filteredCourses.length + 1,
// separatorBuilder: (context, index) =>
// const SizedBox(height: 10.0),
// itemBuilder: (context, index) {
// if (index == filteredCourses.length) {
// return Center(
// child: loading
// ? const CircularProgressIndicator.adaptive()
// : nextBatch != null
// ? TextButton(
// onPressed: _loadCourses,
// child: Text(L10n.of(context).loadMore),
// )
// : const SizedBox(),
// );
// }
final roomChunk = filteredCourses[index].room;
final courseId = filteredCourses[index].courseId;
final course = coursePlans[courseId];
// final roomChunk = filteredCourses[index].room;
// final courseId = filteredCourses[index].courseId;
// final course = coursePlans[courseId];
final displayname = roomChunk.name ??
roomChunk.canonicalAlias ??
L10n.of(context).emptyChat;
// final displayname = roomChunk.name ??
// roomChunk.canonicalAlias ??
// L10n.of(context).emptyChat;
return Material(
type: MaterialType.transparency,
child: InkWell(
onTap: () => context.go(
'/${widget.route}/course/public/$courseId',
extra: roomChunk,
),
borderRadius: BorderRadius.circular(12.0),
child: Container(
padding: const EdgeInsets.all(12.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.0),
border: Border.all(
color: theme.colorScheme.primary,
),
),
child: Column(
spacing: 4.0,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
spacing: 8.0,
children: [
ImageByUrl(
imageUrl: roomChunk.avatarUrl,
width: 58.0,
borderRadius:
BorderRadius.circular(10.0),
replacement: Avatar(
name: displayname,
borderRadius: BorderRadius.circular(
10.0,
),
size: 58.0,
),
),
Flexible(
child: Column(
spacing: 0.0,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
displayname,
style: theme.textTheme.bodyLarge,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
Row(
spacing: 4.0,
mainAxisSize: MainAxisSize.min,
children: [
const Icon(
Icons.group,
size: 16.0,
),
Text(
L10n.of(context)
.countParticipants(
roomChunk.numJoinedMembers,
),
style: theme
.textTheme.bodyMedium,
),
],
),
],
),
),
],
),
if (course != null) ...[
CourseInfoChips(
courseId,
iconSize: 12.0,
fontSize: 12.0,
),
Text(
course.description,
style: theme.textTheme.bodyMedium,
),
],
const SizedBox(height: 12.0),
HoverBuilder(
builder: (context, hovered) =>
ElevatedButton(
onPressed: () => context.go(
'/${widget.route}/course/public/$courseId',
extra: roomChunk,
),
style: ElevatedButton.styleFrom(
backgroundColor: theme
.colorScheme.primaryContainer
.withAlpha(hovered ? 255 : 200),
foregroundColor: theme
.colorScheme.onPrimaryContainer,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(12.0),
),
),
child: Row(
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Text(
roomChunk.joinRule ==
JoinRules.knock.name
? L10n.of(context).knock
: L10n.of(context).join,
),
],
),
),
),
],
),
),
),
);
},
),
),
],
),
),
),
),
);
}
}
// return Material(
// type: MaterialType.transparency,
// child: InkWell(
// onTap: () => context.go(
// '/${widget.route}/course/public/$courseId',
// extra: roomChunk,
// ),
// borderRadius: BorderRadius.circular(12.0),
// child: Container(
// padding: const EdgeInsets.all(12.0),
// decoration: BoxDecoration(
// borderRadius: BorderRadius.circular(12.0),
// border: Border.all(
// color: theme.colorScheme.primary,
// ),
// ),
// child: Column(
// spacing: 4.0,
// mainAxisSize: MainAxisSize.min,
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Row(
// spacing: 8.0,
// children: [
// ImageByUrl(
// imageUrl: roomChunk.avatarUrl,
// width: 58.0,
// borderRadius:
// BorderRadius.circular(10.0),
// replacement: Avatar(
// name: displayname,
// borderRadius: BorderRadius.circular(
// 10.0,
// ),
// size: 58.0,
// ),
// ),
// Flexible(
// child: Column(
// spacing: 0.0,
// crossAxisAlignment:
// CrossAxisAlignment.start,
// children: [
// Text(
// displayname,
// style: theme.textTheme.bodyLarge,
// maxLines: 2,
// overflow: TextOverflow.ellipsis,
// ),
// Row(
// spacing: 4.0,
// mainAxisSize: MainAxisSize.min,
// children: [
// const Icon(
// Icons.group,
// size: 16.0,
// ),
// Text(
// L10n.of(context)
// .countParticipants(
// roomChunk.numJoinedMembers,
// ),
// style: theme
// .textTheme.bodyMedium,
// ),
// ],
// ),
// ],
// ),
// ),
// ],
// ),
// if (course != null) ...[
// CourseInfoChips(
// courseId,
// iconSize: 12.0,
// fontSize: 12.0,
// ),
// Text(
// course.description,
// style: theme.textTheme.bodyMedium,
// ),
// ],
// const SizedBox(height: 12.0),
// HoverBuilder(
// builder: (context, hovered) =>
// ElevatedButton(
// onPressed: () => context.go(
// '/${widget.route}/course/public/$courseId',
// extra: roomChunk,
// ),
// style: ElevatedButton.styleFrom(
// backgroundColor: theme
// .colorScheme.primaryContainer
// .withAlpha(hovered ? 255 : 200),
// foregroundColor: theme
// .colorScheme.onPrimaryContainer,
// shape: RoundedRectangleBorder(
// borderRadius:
// BorderRadius.circular(12.0),
// ),
// ),
// child: Row(
// mainAxisAlignment:
// MainAxisAlignment.center,
// children: [
// Text(
// roomChunk.joinRule ==
// JoinRules.knock.name
// ? L10n.of(context).knock
// : L10n.of(context).join,
// ),
// ],
// ),
// ),
// ),
// ],
// ),
// ),
// ),
// );
// },
// ),
// ),
// ],
// ),
// ),
// ),
// ),
// );
// }
// }