feat: allow users to knock on public courses (#5202)

This commit is contained in:
ggurdin 2026-01-15 14:20:20 -05:00 committed by GitHub
parent 3be47ab6b0
commit d05e45fc3b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 78 additions and 12 deletions

View file

@ -13,6 +13,7 @@ import 'package:fluffychat/pangea/course_plans/courses/course_plan_model.dart';
import 'package:fluffychat/pangea/course_plans/courses/course_plan_room_extension.dart';
import 'package:fluffychat/pangea/events/constants/pangea_event_types.dart';
import 'package:fluffychat/pangea/spaces/client_spaces_extension.dart';
import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart';
import 'package:fluffychat/widgets/matrix.dart';
enum SelectedCourseMode { launch, addToSpace, join }
@ -74,7 +75,9 @@ class SelectedCourseController extends State<SelectedCourse>
case SelectedCourseMode.addToSpace:
return L10n.of(context).addCoursePlan;
case SelectedCourseMode.join:
return L10n.of(context).joinWithClassCode;
return widget.roomChunk?.joinRule == JoinRules.knock.name
? L10n.of(context).knock
: L10n.of(context).join;
}
}
@ -152,16 +155,36 @@ class SelectedCourseController extends State<SelectedCourse>
}
final client = Matrix.of(context).client;
final roomId = await client.joinRoom(
widget.roomChunk!.roomId,
);
final room = client.getRoomById(roomId);
if (room == null || room.membership != Membership.join) {
await client.waitForRoomInSync(roomId, join: true);
final r = client.getRoomById(widget.roomChunk!.roomId);
if (r != null && r.membership == Membership.join) {
if (mounted) {
context.go("/rooms/spaces/${r.id}/details");
}
return;
}
if (client.getRoomById(roomId) == null) {
final knock = widget.roomChunk!.joinRule == JoinRules.knock.name;
final roomId = widget.roomChunk != null && knock
? await client.knockRoom(widget.roomChunk!.roomId)
: await client.joinRoom(widget.roomChunk!.roomId);
Room? room = client.getRoomById(roomId);
if (!knock && room == null) {
await client.waitForRoomInSync(roomId);
room = client.getRoomById(roomId);
}
if (knock && room == null) {
Navigator.of(context).pop();
await showOkAlertDialog(
context: context,
title: L10n.of(context).youHaveKnocked,
message: L10n.of(context).pleaseWaitUntilInvited,
);
return;
}
if (room == null) {
throw Exception("Failed to join room");
}

View file

@ -283,7 +283,8 @@ class SelectedCourseView extends StatelessWidget {
),
child: Row(
spacing: 8.0,
mainAxisSize: MainAxisSize.min,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
const Icon(Icons.map_outlined),
Text(

View file

@ -15,6 +15,7 @@ import 'package:fluffychat/pangea/course_plans/courses/get_localized_courses_req
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 {
@ -67,8 +68,7 @@ class PublicCoursesPageState extends State<PublicCoursesPage> {
r.id == c.room.roomId &&
r.membership == Membership.join,
) &&
coursePlans.containsKey(c.courseId) &&
c.room.joinRule == 'public',
coursePlans.containsKey(c.courseId),
)
.toList();
@ -83,6 +83,15 @@ class PublicCoursesPageState extends State<PublicCoursesPage> {
).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;
});
return filtered;
}
@ -333,6 +342,39 @@ class PublicCoursesPageState extends State<PublicCoursesPage> {
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,
),
],
),
),
),
],
),
),