ideal case of private class code

pull/1423/head
WilsonLe 1 year ago
parent dfb45bb20e
commit 550c3ab699

@ -150,7 +150,10 @@ class NewSpaceController extends State<NewSpace> {
try { try {
final avatar = this.avatar; final avatar = this.avatar;
avatarUrl ??= avatar == null ? null : await client.uploadContent(avatar); avatarUrl ??= avatar == null ? null : await client.uploadContent(avatar);
final classCode = await SpaceCodeUtil.generateSpaceCode(client);
if (classCode == null) {
return;
}
final spaceId = await client.createRoom( final spaceId = await client.createRoom(
// #Pangea // #Pangea
// preset: publicGroup // preset: publicGroup
@ -164,7 +167,7 @@ class NewSpaceController extends State<NewSpace> {
// roomAliasName: publicGroup // roomAliasName: publicGroup
// ? nameController.text.trim().toLowerCase().replaceAll(' ', '_') // ? nameController.text.trim().toLowerCase().replaceAll(' ', '_')
// : null, // : null,
roomAliasName: SpaceCodeUtil.generateSpaceCode(), roomAliasName: classCode,
// Pangea# // Pangea#
name: nameController.text.trim(), name: nameController.text.trim(),
topic: topicController.text.isEmpty ? null : topicController.text, topic: topicController.text.isEmpty ? null : topicController.text,
@ -178,14 +181,21 @@ class NewSpaceController extends State<NewSpace> {
: null, : null,
// Pangea# // Pangea#
initialState: [ initialState: [
// #Pangea
...initialState,
// Pangea#
if (avatar != null) if (avatar != null)
sdk.StateEvent( sdk.StateEvent(
type: sdk.EventTypes.RoomAvatar, type: sdk.EventTypes.RoomAvatar,
content: {'url': avatarUrl.toString()}, content: {'url': avatarUrl.toString()},
), ),
// #Pangea sdk.StateEvent(
...initialState, type: sdk.EventTypes.RoomJoinRules,
// Pangea# content: {
'join_rule': 'knock',
'access_code': classCode,
},
),
], ],
); );
// #Pangea // #Pangea

@ -123,4 +123,8 @@ class ModelKey {
static const String prevEventId = "prev_event_id"; static const String prevEventId = "prev_event_id";
static const String prevLastUpdated = "prev_last_updated"; static const String prevLastUpdated = "prev_last_updated";
// room code
static const String joinRule = "join_rule";
static const String accessCode = "access_code";
} }

@ -1,7 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert';
import 'dart:developer'; import 'dart:developer';
import 'package:collection/collection.dart';
import 'package:fluffychat/pangea/constants/local.key.dart'; import 'package:fluffychat/pangea/constants/local.key.dart';
import 'package:fluffychat/pangea/constants/pangea_event_types.dart'; import 'package:fluffychat/pangea/constants/pangea_event_types.dart';
import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart';
@ -9,15 +9,15 @@ import 'package:fluffychat/pangea/extensions/client_extension/client_extension.d
import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart';
import 'package:fluffychat/pangea/models/space_model.dart'; import 'package:fluffychat/pangea/models/space_model.dart';
import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart';
import 'package:fluffychat/pangea/utils/firebase_analytics.dart';
import 'package:fluffychat/pangea/utils/space_code.dart'; import 'package:fluffychat/pangea/utils/space_code.dart';
import 'package:fluffychat/widgets/matrix.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:matrix/matrix.dart'; import 'package:matrix/matrix.dart';
import '../../widgets/matrix.dart';
import '../utils/firebase_analytics.dart';
import 'base_controller.dart'; import 'base_controller.dart';
class ClassController extends BaseController { class ClassController extends BaseController {
@ -65,47 +65,56 @@ class ClassController extends BaseController {
} }
Future<void> joinClasswithCode(BuildContext context, String classCode) async { Future<void> joinClasswithCode(BuildContext context, String classCode) async {
final client = Matrix.of(context).client;
try { try {
final QueryPublicRoomsResponse queryPublicRoomsResponse = final knockResponse = await client.httpClient.post(
await Matrix.of(context).client.queryPublicRooms( Uri.parse(
limit: 1, '${client.homeserver}/_synapse/client/pangea/v1/knock_with_code',
filter: PublicRoomQueryFilter(genericSearchTerm: classCode), ),
); headers: {
'Content-Type': 'application/json',
final PublicRoomsChunk? classChunk = 'Authorization': 'Bearer ${client.accessToken}',
queryPublicRoomsResponse.chunk.firstWhereOrNull((element) { },
return element.canonicalAlias?.replaceAll("#", "").split(":")[0] == body: jsonEncode({'access_code': classCode}),
classCode; );
}); if (knockResponse.statusCode != 200) {
if (classChunk == null) {
SpaceCodeUtil.messageSnack( SpaceCodeUtil.messageSnack(
context, context,
L10n.of(context)!.unableToFindClass, L10n.of(context)!.unableToFindClass,
); );
return; return;
} }
final knockResult = jsonDecode(knockResponse.body);
final foundClasses = knockResult['rooms'];
if (!(foundClasses is List<String> && foundClasses.isNotEmpty)) {
SpaceCodeUtil.messageSnack(
context,
L10n.of(context)!.unableToFindClass,
);
return;
}
final chosenClassId = foundClasses.first;
await client.joinRoomById(chosenClassId);
if (_pangeaController.matrixState.client.rooms if (_pangeaController.matrixState.client.rooms
.any((room) => room.id == classChunk.roomId)) { .any((room) => room.id == chosenClassId)) {
setActiveSpaceIdInChatListController(classChunk.roomId); setActiveSpaceIdInChatListController(chosenClassId);
SpaceCodeUtil.messageSnack(context, L10n.of(context)!.alreadyInClass); SpaceCodeUtil.messageSnack(context, L10n.of(context)!.alreadyInClass);
return; return;
} }
await _pangeaController.matrixState.client.joinRoom(classChunk.roomId); await _pangeaController.matrixState.client.joinRoom(chosenClassId);
if (_pangeaController.matrixState.client.getRoomById(classChunk.roomId) == if (_pangeaController.matrixState.client.getRoomById(chosenClassId) ==
null) { null) {
await _pangeaController.matrixState.client.waitForRoomInSync( await _pangeaController.matrixState.client.waitForRoomInSync(
classChunk.roomId, chosenClassId,
join: true, join: true,
); );
} }
// If the room is full, leave // If the room is full, leave
final room = final room =
_pangeaController.matrixState.client.getRoomById(classChunk.roomId); _pangeaController.matrixState.client.getRoomById(chosenClassId);
if (room == null) { if (room == null) {
return; return;
} }
@ -121,12 +130,12 @@ class ClassController extends BaseController {
return; return;
} }
setActiveSpaceIdInChatListController(classChunk.roomId); setActiveSpaceIdInChatListController(chosenClassId);
// add the user's analytics room to this joined space // add the user's analytics room to this joined space
// so their teachers can join them via the space hierarchy // so their teachers can join them via the space hierarchy
final Room? joinedSpace = final Room? joinedSpace =
_pangeaController.matrixState.client.getRoomById(classChunk.roomId); _pangeaController.matrixState.client.getRoomById(chosenClassId);
// when possible, add user's analytics room the to space they joined // when possible, add user's analytics room the to space they joined
joinedSpace?.addAnalyticsRoomsToSpace(); joinedSpace?.addAnalyticsRoomsToSpace();

@ -15,8 +15,14 @@ extension SpaceRoomExtension on Room {
} }
return "Not in a class!"; return "Not in a class!";
} }
final roomJoinRules = getState(EventTypes.RoomJoinRules, "");
return canonicalAlias.replaceAll(":$domainString", "").replaceAll("#", ""); if (roomJoinRules != null) {
final accessCode = roomJoinRules.content.tryGet(ModelKey.accessCode);
if (accessCode is String) {
return accessCode;
}
}
return "No class code!";
} }
void _checkClass() { void _checkClass() {

@ -1,10 +1,10 @@
import 'dart:math'; import 'dart:convert';
import 'package:adaptive_dialog/adaptive_dialog.dart'; import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:fluffychat/pangea/controllers/pangea_controller.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:matrix/matrix.dart';
import '../controllers/pangea_controller.dart';
class SpaceCodeUtil { class SpaceCodeUtil {
static const codeLength = 6; static const codeLength = 6;
@ -13,11 +13,25 @@ class SpaceCodeUtil {
return spacecode == null || spacecode.length > 4; return spacecode == null || spacecode.length > 4;
} }
static String generateSpaceCode() { static Future<String?> generateSpaceCode(Client client) async {
final r = Random(); final response = await client.httpClient.get(
const chars = 'AaBbCcDdEeFfGgHhiJjKkLMmNnoPpQqRrSsTtUuVvWwXxYyZz1234567890'; Uri.parse(
return List.generate(codeLength, (index) => chars[r.nextInt(chars.length)]) '${client.homeserver}/_synapse/client/pangea/v1/request_room_code',
.join(); ),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ${client.accessToken}',
},
);
if (response.statusCode != 200) {
return null;
}
final roomCodeResult = jsonDecode(response.body);
if (roomCodeResult['access_code'] is String) {
return roomCodeResult['access_code'] as String;
} else {
throw Exception('Invalid response, access_code not found $response');
}
} }
static Future<void> joinWithSpaceCodeDialog( static Future<void> joinWithSpaceCodeDialog(

Loading…
Cancel
Save